blockwatch-cc/tzgo

Contract receipt slow to return

Closed this issue · 4 comments

Tested Versions: 1.17.1, 1.17.2

Below is a simplified version of what I am using to interact with a smart contract entrypoint that takes an address and amount as parameters. For reference, the contract releases some funds (the amount) to the receiver address from the contract. Watching the explorer I can see the operation is included not long after the contract call occurs, it seems however, that the receipt return always take a lengthy amount of time.

Regardless of the various options I alter the whole process takes around 75-95 seconds. Using some node libraries I can run comparable code with an average duration of approximately:

  • 1 Confirmation - 12 seconds
  • 2 Confirmations - 32 seconds
  • 4 Confirmations - 59 seconds

Changing the confirmations in this case seemingly has no impact and the time taken seems vastly increased. Is there any reason for the increased time that I am missing?

package main

import (
	"context"
	"fmt"
	"math/big"

	"blockwatch.cc/tzgo/contract"
	"blockwatch.cc/tzgo/micheline"
	"blockwatch.cc/tzgo/rpc"
	"blockwatch.cc/tzgo/signer"
	"blockwatch.cc/tzgo/tezos"
)

const rpcUrl = "https://mainnet.smartpy.io"
const contractAddress = "contract address"
const secretKey = "the key"

const entryPoint = "entry_point"
const receiver = "receiver address"
const amount int64 = 1

func main() {
	ctx := context.Background()

	conn, _ := rpc.NewClient(rpcUrl, nil)
	_ = conn.Init(ctx)

	ca, _ := tezos.ParseAddress(contractAddress)
	cnt := contract.NewContract(ca, conn)

	sk, _ := tezos.ParsePrivateKey(secretKey)
	to, _ := tezos.ParseAddress(receiver)

	args := contract.NewTxArgs()
	args.WithParameters(micheline.Parameters{
		Entrypoint: entryPoint,
		Value: micheline.NewPair(
			micheline.NewBytes(to.EncodePadded()),
			micheline.NewNat(big.NewInt(amount)),
		),
	})

	opts := rpc.DefaultOptions
	opts.Signer = signer.NewFromKey(sk)
	opts.Confirmations = 1

	receipt, _ := cnt.Call(ctx, args, &opts)

	fmt.Println("Transaction Receipt:", receipt)
}
echa commented

Hm, your code and TzGo 1.17.2 look correct. I changed the observer implementation in v1.17.3 and its worth a try, however, I suspect something else.

When you observe the output between

you see the smartpy node is lagging one or multiple blocks behind. This looks like a severe overload on their end.

Have you performed the "faster" tests with the same node and at around the same time? Maybe worth using a local node (a rolling mode node is sufficient).

Yes, all the const values are the same across the two implementations. Tests were performed one after the other and behavior is the same across multiple runs.

I will test 1.17.3 and I will also test with a few different node providers to see if this changes anything.

The only other thing of note is that the confirmations don't seem to impact the time in the TzGo implementation and the returned receipt is quite verbose, I assume the receipt requires a number of calls, but this is just an assumption.

I'll update with any results, many thanks for the response.

@echa I swapped out the url from smartpy to tzstats and after 10 runs the times range from 4-20 seconds with an average of 12 seconds; which matches the node implementation. I ran a test with smartpy just before and it was 86 seconds. I am still using v1.17.2. I'm not sure why the same issue with smartpy would not be present in the node implementation, but regardless you seem to have hit the nail on the head here.

I'll close the issue, I am extremely grateful for your help.

echa commented

Just speculating here, but it may be a less scalable HTTP stack in Octez vs. the Go smart proxy that we use behind TzStats / TzPro. The /monitor/heads/main endpoint is implemented as HTTP long-poll and results are streamed as soon as a new block is attached to the chain.

It may be that either the Smartpy node does not validate blocks fast enough or its HTTP server is choked by high load and many concurrent connections. Smartpy uses Cloudflare and initial connection setup is fast, but then the HTTP conn stalls for very long before it immediately flushes data of several blocks. This explains your observation that a change in TzGo confirmations does not seem to have any impact.

Anyways, if you decide to use a public node, we're closing down the TzStats API soon and migrate users over to TzPro.io if that matters to you.