Some checks failed
Vulncheck / Vulncheck (push) Successful in 1m3s
Build / Build Components (push) Has been cancelled
Pre-commit hooks / Pre-commit (push) Successful in 1m25s
OCI image / Build container images (push) Has been cancelled
Tests and linters / Lint (push) Has been cancelled
Tests and linters / Tests (push) Has been cancelled
Tests and linters / Tests with -race (push) Has been cancelled
Tests and linters / Staticcheck (push) Has been cancelled
Tests and linters / gopls check (push) Has been cancelled
Tests and linters / Run gofumpt (push) Has been cancelled
Each stage waits until transaction persists. This is needed to ensure the next stage will see the result of the previous one. However, some of the stages do not depend one on another, so we may execute them in parallel. `AwaitDisabled` flag is used to localize this batching on the code level. We could've removed `AwaitTx()` from respective stages, but it seems more error prone. Close #652. Change-Id: Ib9c6f6cd5e0db0f31aa1cda8e127b1fad5166336 Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
139 lines
3.5 KiB
Go
139 lines
3.5 KiB
Go
package helper
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
|
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
|
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
|
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
|
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
|
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
|
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
|
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
// Client represents N3 client interface capable of test-invoking scripts
|
|
// and sending signed transactions to chain.
|
|
type Client interface {
|
|
actor.RPCActor
|
|
|
|
GetNativeContracts() ([]state.Contract, error)
|
|
GetApplicationLog(util.Uint256, *trigger.Type) (*result.ApplicationLog, error)
|
|
}
|
|
|
|
type HashVUBPair struct {
|
|
Hash util.Uint256
|
|
Vub uint32
|
|
}
|
|
|
|
type ClientContext struct {
|
|
Client Client // a raw neo-go client OR a local chain implementation
|
|
CommitteeAct *actor.Actor // committee actor with the Global witness scope
|
|
ReadOnlyInvoker *invoker.Invoker // R/O contract invoker, does not contain any signer
|
|
SentTxs []HashVUBPair
|
|
|
|
AwaitDisabled bool
|
|
}
|
|
|
|
func NewRemoteClient(v *viper.Viper) (Client, error) {
|
|
// number of opened connections
|
|
// by neo-go client per one host
|
|
const (
|
|
maxConnsPerHost = 10
|
|
requestTimeout = time.Second * 10
|
|
)
|
|
|
|
ctx := context.Background()
|
|
endpoint := v.GetString(commonflags.EndpointFlag)
|
|
if endpoint == "" {
|
|
return nil, errors.New("missing endpoint")
|
|
}
|
|
|
|
var cfg *tls.Config
|
|
if rootCAs := v.GetStringSlice("tls.trusted_ca_list"); len(rootCAs) != 0 {
|
|
certFile := v.GetString("tls.certificate")
|
|
keyFile := v.GetString("tls.key")
|
|
|
|
tlsConfig, err := rpcclient.TLSClientConfig(rootCAs, certFile, keyFile)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
cfg = tlsConfig
|
|
}
|
|
c, err := rpcclient.New(ctx, endpoint, rpcclient.Options{
|
|
MaxConnsPerHost: maxConnsPerHost,
|
|
RequestTimeout: requestTimeout,
|
|
TLSClientConfig: cfg,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := c.Init(); err != nil {
|
|
return nil, err
|
|
}
|
|
return c, nil
|
|
}
|
|
|
|
func defaultClientContext(c Client, committeeAcc *wallet.Account) (*ClientContext, error) {
|
|
commAct, err := actor.New(c, []actor.SignerAccount{{
|
|
Signer: transaction.Signer{
|
|
Account: committeeAcc.Contract.ScriptHash(),
|
|
Scopes: transaction.Global,
|
|
},
|
|
Account: committeeAcc,
|
|
}})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &ClientContext{
|
|
Client: c,
|
|
CommitteeAct: commAct,
|
|
ReadOnlyInvoker: invoker.New(c, nil),
|
|
}, nil
|
|
}
|
|
|
|
func (c *ClientContext) SendTx(tx *transaction.Transaction, cmd *cobra.Command, await bool) error {
|
|
h, err := c.Client.SendRawTransaction(tx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if h != tx.Hash() {
|
|
return fmt.Errorf("sent and actual tx hashes mismatch:\n\tsent: %v\n\tactual: %v", tx.Hash().StringLE(), h.StringLE())
|
|
}
|
|
|
|
c.SentTxs = append(c.SentTxs, HashVUBPair{Hash: h, Vub: tx.ValidUntilBlock})
|
|
|
|
if await {
|
|
return c.AwaitTx(cmd)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c *ClientContext) AwaitTx(cmd *cobra.Command) error {
|
|
if len(c.SentTxs) == 0 || c.AwaitDisabled {
|
|
return nil
|
|
}
|
|
|
|
if local, ok := c.Client.(*LocalClient); ok {
|
|
if err := local.putTransactions(); err != nil {
|
|
return fmt.Errorf("can't persist transactions: %w", err)
|
|
}
|
|
}
|
|
|
|
err := AwaitTx(cmd, c.Client, c.SentTxs)
|
|
c.SentTxs = c.SentTxs[:0]
|
|
|
|
return err
|
|
}
|