2024-01-31 14:26:26 +00:00
|
|
|
package util
|
2021-07-19 11:04:19 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2021-10-18 12:20:04 +00:00
|
|
|
"errors"
|
2022-04-07 08:14:10 +00:00
|
|
|
"fmt"
|
2021-11-30 11:45:40 +00:00
|
|
|
"time"
|
2021-07-19 11:04:19 +00:00
|
|
|
|
2022-04-07 08:10:35 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
2021-11-30 11:45:40 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
2022-06-02 14:24:03 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
2022-07-28 16:22:32 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
|
2022-09-05 12:45:38 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
|
2022-04-07 08:10:35 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
2021-11-30 11:45:40 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
2022-04-07 08:10:35 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
2021-11-30 11:45:40 +00:00
|
|
|
"github.com/spf13/cobra"
|
2021-07-19 11:04:19 +00:00
|
|
|
"github.com/spf13/viper"
|
|
|
|
)
|
|
|
|
|
2022-04-07 08:10:35 +00:00
|
|
|
// Client represents N3 client interface capable of test-invoking scripts
|
|
|
|
// and sending signed transactions to chain.
|
|
|
|
type Client interface {
|
2022-10-21 08:01:17 +00:00
|
|
|
invoker.RPCInvoke
|
|
|
|
|
2022-04-07 08:10:35 +00:00
|
|
|
GetBlockCount() (uint32, error)
|
|
|
|
GetNativeContracts() ([]state.NativeContract, error)
|
|
|
|
GetApplicationLog(util.Uint256, *trigger.Type) (*result.ApplicationLog, error)
|
2022-08-29 19:31:32 +00:00
|
|
|
GetVersion() (*result.Version, error)
|
2022-04-07 08:10:35 +00:00
|
|
|
SendRawTransaction(*transaction.Transaction) (util.Uint256, error)
|
2022-06-02 14:24:03 +00:00
|
|
|
GetCommittee() (keys.PublicKeys, error)
|
2022-08-29 19:31:32 +00:00
|
|
|
CalculateNetworkFee(tx *transaction.Transaction) (int64, error)
|
2022-04-07 08:10:35 +00:00
|
|
|
}
|
|
|
|
|
2024-01-31 14:26:26 +00:00
|
|
|
type HashVUBPair struct {
|
|
|
|
Hash util.Uint256
|
|
|
|
Vub uint32
|
2022-09-14 10:11:53 +00:00
|
|
|
}
|
|
|
|
|
2024-01-31 14:26:26 +00:00
|
|
|
type ClientContext struct {
|
2022-09-05 12:45:38 +00:00
|
|
|
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
|
2024-01-31 14:26:26 +00:00
|
|
|
SentTxs []HashVUBPair
|
2021-11-30 11:45:40 +00:00
|
|
|
}
|
|
|
|
|
2024-01-31 14:26:26 +00:00
|
|
|
func GetN3Client(v *viper.Viper) (Client, error) {
|
2021-12-15 18:05:21 +00:00
|
|
|
// number of opened connections
|
|
|
|
// by neo-go client per one host
|
2022-02-07 13:58:56 +00:00
|
|
|
const (
|
|
|
|
maxConnsPerHost = 10
|
|
|
|
requestTimeout = time.Second * 10
|
|
|
|
)
|
2021-12-15 18:05:21 +00:00
|
|
|
|
2022-02-07 13:58:56 +00:00
|
|
|
ctx := context.Background()
|
2024-01-31 14:26:26 +00:00
|
|
|
endpoint := v.GetString(EndpointFlag)
|
2021-10-18 12:20:04 +00:00
|
|
|
if endpoint == "" {
|
|
|
|
return nil, errors.New("missing endpoint")
|
|
|
|
}
|
2022-07-28 16:22:32 +00:00
|
|
|
c, err := rpcclient.New(ctx, endpoint, rpcclient.Options{
|
2022-02-07 13:58:56 +00:00
|
|
|
MaxConnsPerHost: maxConnsPerHost,
|
|
|
|
RequestTimeout: requestTimeout,
|
|
|
|
})
|
2021-07-19 11:04:19 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if err := c.Init(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return c, nil
|
|
|
|
}
|
2021-11-30 11:45:40 +00:00
|
|
|
|
2024-01-31 14:26:26 +00:00
|
|
|
func DefaultClientContext(c Client, committeeAcc *wallet.Account) (*ClientContext, error) {
|
|
|
|
commAct, err := NewActor(c, committeeAcc)
|
2022-09-05 12:45:38 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2021-11-30 11:57:58 +00:00
|
|
|
}
|
2022-09-05 12:45:38 +00:00
|
|
|
|
2024-01-31 14:26:26 +00:00
|
|
|
return &ClientContext{
|
2022-09-05 12:45:38 +00:00
|
|
|
Client: c,
|
|
|
|
CommitteeAct: commAct,
|
|
|
|
ReadOnlyInvoker: invoker.New(c, nil),
|
|
|
|
}, nil
|
2021-11-30 11:57:58 +00:00
|
|
|
}
|
|
|
|
|
2024-01-31 14:26:26 +00:00
|
|
|
func (c *ClientContext) SendTx(tx *transaction.Transaction, cmd *cobra.Command, await bool) error {
|
2021-11-30 11:45:40 +00:00
|
|
|
h, err := c.Client.SendRawTransaction(tx)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-04-07 08:14:10 +00:00
|
|
|
if h != tx.Hash() {
|
|
|
|
return fmt.Errorf("sent and actual tx hashes mismatch:\n\tsent: %v\n\tactual: %v", tx.Hash().StringLE(), h.StringLE())
|
|
|
|
}
|
|
|
|
|
2024-01-31 14:26:26 +00:00
|
|
|
c.SentTxs = append(c.SentTxs, HashVUBPair{Hash: h, Vub: tx.ValidUntilBlock})
|
2021-11-30 11:45:40 +00:00
|
|
|
|
|
|
|
if await {
|
2024-01-31 14:26:26 +00:00
|
|
|
return c.AwaitTx(cmd)
|
2021-11-30 11:45:40 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2024-01-31 14:26:26 +00:00
|
|
|
|
|
|
|
func (c *ClientContext) AwaitTx(cmd *cobra.Command) error {
|
|
|
|
if len(c.SentTxs) == 0 {
|
|
|
|
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
|
|
|
|
}
|