Merge pull request #1067 from nspcc-dev/network-in-the-hash

Add network magic to block/transaction hashes (IDs)
This commit is contained in:
Roman Khimov 2020-06-18 13:51:17 +03:00 committed by GitHub
commit feb7d26e00
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
61 changed files with 614 additions and 448 deletions

77
cli/options/options.go Normal file
View file

@ -0,0 +1,77 @@
/*
Package options contains a set of common CLI options and helper functions to use them.
*/
package options
import (
"context"
"errors"
"time"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/rpc/client"
"github.com/urfave/cli"
)
// DefaultTimeout is the default timeout used for RPC requests.
const DefaultTimeout = 10 * time.Second
// RPCEndpointFlag is a long flag name for RPC endpoint. It can be used to
// check for flag presence in the context.
const RPCEndpointFlag = "rpc-endpoint"
// Network is a set of flags for choosing the network to operate on
// (privnet/mainnet/testnet).
var Network = RPC[2:]
// RPC is a set of flags used for RPC connections (endpoint and timeout).
var RPC = []cli.Flag{
cli.StringFlag{
Name: RPCEndpointFlag + ", r",
Usage: "RPC node address",
},
cli.DurationFlag{
Name: "timeout, s",
Usage: "Timeout for the operation (10 seconds by default)",
},
cli.BoolFlag{Name: "privnet, p"},
cli.BoolFlag{Name: "mainnet, m"},
cli.BoolFlag{Name: "testnet, t"},
}
var errNoEndpoint = errors.New("no RPC endpoint specified, use option '--" + RPCEndpointFlag + "' or '-r'")
// GetNetwork examines Context's flags and returns the appropriate network. It
// defaults to PrivNet if no flags are given.
func GetNetwork(ctx *cli.Context) netmode.Magic {
var net = netmode.PrivNet
if ctx.Bool("testnet") {
net = netmode.TestNet
}
if ctx.Bool("mainnet") {
net = netmode.MainNet
}
return net
}
// GetTimeoutContext returns a context.Context with default of user-set timeout.
func GetTimeoutContext(ctx *cli.Context) (context.Context, func()) {
dur := ctx.Duration("timeout")
if dur == 0 {
dur = DefaultTimeout
}
return context.WithTimeout(context.Background(), dur)
}
// GetRPCClient returns an RPC client instance for the given Context.
func GetRPCClient(gctx context.Context, ctx *cli.Context) (*client.Client, cli.ExitCoder) {
endpoint := ctx.String(RPCEndpointFlag)
if len(endpoint) == 0 {
return nil, cli.NewExitError(errNoEndpoint, 1)
}
c, err := client.New(gctx, endpoint, client.Options{Network: GetNetwork(ctx)})
if err != nil {
return nil, cli.NewExitError(err, 1)
}
return c, nil
}

View file

@ -6,6 +6,7 @@ import (
"os"
"os/signal"
"github.com/nspcc-dev/neo-go/cli/options"
"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/core"
"github.com/nspcc-dev/neo-go/pkg/core/block"
@ -24,11 +25,9 @@ import (
func NewCommands() []cli.Command {
var cfgFlags = []cli.Flag{
cli.StringFlag{Name: "config-path"},
cli.BoolFlag{Name: "privnet, p"},
cli.BoolFlag{Name: "mainnet, m"},
cli.BoolFlag{Name: "testnet, t"},
cli.BoolFlag{Name: "debug, d"},
}
cfgFlags = append(cfgFlags, options.Network...)
var cfgWithCountFlags = make([]cli.Flag, len(cfgFlags))
copy(cfgWithCountFlags, cfgFlags)
cfgWithCountFlags = append(cfgWithCountFlags,
@ -107,18 +106,11 @@ func newGraceContext() context.Context {
// getConfigFromContext looks at path and mode flags in the given config and
// returns appropriate config.
func getConfigFromContext(ctx *cli.Context) (config.Config, error) {
var net = config.ModePrivNet
if ctx.Bool("testnet") {
net = config.ModeTestNet
}
if ctx.Bool("mainnet") {
net = config.ModeMainNet
}
configPath := "./config"
if argCp := ctx.String("config-path"); argCp != "" {
configPath = argCp
}
return config.Load(configPath, net)
return config.Load(configPath, options.GetNetwork(ctx))
}
// handleLoggingParams reads logging parameters.
@ -290,7 +282,7 @@ func restoreDB(ctx *cli.Context) error {
default:
}
bytes, err := readBlock(reader)
block := &block.Block{}
block := block.New(cfg.ProtocolConfiguration.Magic)
newReader := io.NewBinReaderFromBuf(bytes)
block.DecodeBinary(newReader)
if err != nil {

View file

@ -2,7 +2,6 @@ package smartcontract
import (
"bytes"
"context"
"encoding/hex"
"encoding/json"
"fmt"
@ -14,11 +13,11 @@ import (
"github.com/go-yaml/yaml"
"github.com/nspcc-dev/neo-go/cli/flags"
"github.com/nspcc-dev/neo-go/cli/options"
"github.com/nspcc-dev/neo-go/pkg/compiler"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/rpc/client"
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
@ -32,7 +31,6 @@ import (
)
var (
errNoEndpoint = errors.New("no RPC endpoint specified, use option '--endpoint' or '-e'")
errNoInput = errors.New("no input file was found, specify an input file with the '--in or -i' flag")
errNoConfFile = errors.New("no config file was found, specify a config file with the '--config' or '-c' flag")
errNoMethod = errors.New("no method specified for function invocation command")
@ -41,10 +39,6 @@ var (
errNoSmartContractName = errors.New("no name was provided, specify the '--name or -n' flag")
errFileExist = errors.New("A file with given smart-contract name already exists")
endpointFlag = cli.StringFlag{
Name: "endpoint, e",
Usage: "trusted RPC endpoint address (like 'http://localhost:20331')",
}
walletFlag = cli.StringFlag{
Name: "wallet, w",
Usage: "wallet to use to get the key for transaction signing",
@ -76,6 +70,33 @@ func Main(op string, args []interface{}) {
// NewCommands returns 'contract' command.
func NewCommands() []cli.Command {
testInvokeScriptFlags := []cli.Flag{
cli.StringFlag{
Name: "in, i",
Usage: "Input location of the avm file that needs to be invoked",
},
}
testInvokeScriptFlags = append(testInvokeScriptFlags, options.RPC...)
deployFlags := []cli.Flag{
cli.StringFlag{
Name: "in, i",
Usage: "Input file for the smart contract (*.avm)",
},
cli.StringFlag{
Name: "config, c",
Usage: "configuration input file (*.yml)",
},
walletFlag,
addressFlag,
gasFlag,
}
deployFlags = append(deployFlags, options.RPC...)
invokeFunctionFlags := []cli.Flag{
walletFlag,
addressFlag,
gasFlag,
}
invokeFunctionFlags = append(invokeFunctionFlags, options.RPC...)
return []cli.Command{{
Name: "contract",
Usage: "compile - debug - deploy smart contracts",
@ -121,42 +142,24 @@ func NewCommands() []cli.Command {
to it).
`,
Action: contractDeploy,
Flags: []cli.Flag{
cli.StringFlag{
Name: "in, i",
Usage: "Input file for the smart contract (*.avm)",
},
cli.StringFlag{
Name: "config, c",
Usage: "configuration input file (*.yml)",
},
endpointFlag,
walletFlag,
addressFlag,
gasFlag,
},
Flags: deployFlags,
},
{
Name: "invokefunction",
Usage: "invoke deployed contract on the blockchain",
UsageText: "neo-go contract invokefunction -e endpoint -w wallet [-a address] [-g gas] scripthash [method] [arguments...] [--] [cosigners...]",
UsageText: "neo-go contract invokefunction -r endpoint -w wallet [-a address] [-g gas] scripthash [method] [arguments...] [--] [cosigners...]",
Description: `Executes given (as a script hash) deployed script with the given method,
arguments and cosigners. See testinvokefunction documentation for the details
about parameters. It differs from testinvokefunction in that this command
sends an invocation transaction to the network.
`,
Action: invokeFunction,
Flags: []cli.Flag{
endpointFlag,
walletFlag,
addressFlag,
gasFlag,
},
Flags: invokeFunctionFlags,
},
{
Name: "testinvokefunction",
Usage: "invoke deployed contract on the blockchain (test mode)",
UsageText: "neo-go contract testinvokefunction -e endpoint scripthash [method] [arguments...] [--] [cosigners...]",
UsageText: "neo-go contract testinvokefunction -r endpoint scripthash [method] [arguments...] [--] [cosigners...]",
Description: `Executes given (as a script hash) deployed script with the given method,
arguments and cosigners. If no method is given "" is passed to the script, if
no arguments are given, an empty array is passed, if no cosigners are given,
@ -247,25 +250,17 @@ func NewCommands() []cli.Command {
* '0000000009070e030d0f0e020d0c06050e030c02:CalledByEntry,CustomGroups'
`,
Action: testInvokeFunction,
Flags: []cli.Flag{
endpointFlag,
},
Flags: options.RPC,
},
{
Name: "testinvokescript",
Usage: "Invoke compiled AVM code on the blockchain (test mode, not creating a transaction for it)",
UsageText: "neo-go contract testinvokescript -e endpoint -i input.avm [cosigners...]",
UsageText: "neo-go contract testinvokescript -r endpoint -i input.avm [cosigners...]",
Description: `Executes given compiled AVM instructions with the given set of
cosigners. See testinvokefunction documentation for the details about parameters.
`,
Action: testInvokeScript,
Flags: []cli.Flag{
endpointFlag,
cli.StringFlag{
Name: "in, i",
Usage: "Input location of the avm file that needs to be invoked",
},
},
Flags: testInvokeScriptFlags,
},
{
Name: "init",
@ -407,11 +402,6 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error {
acc *wallet.Account
)
endpoint := ctx.String("endpoint")
if len(endpoint) == 0 {
return cli.NewExitError(errNoEndpoint, 1)
}
args := ctx.Args()
if !args.Present() {
return cli.NewExitError(errNoScriptHash, 1)
@ -455,9 +445,12 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error {
return err
}
}
c, err := client.New(context.TODO(), endpoint, client.Options{})
gctx, cancel := options.GetTimeoutContext(ctx)
defer cancel()
c, err := options.GetRPCClient(gctx, ctx)
if err != nil {
return cli.NewExitError(err, 1)
return err
}
resp, err = c.InvokeFunction(script, operation, params, cosigners)
@ -494,10 +487,6 @@ func testInvokeScript(ctx *cli.Context) error {
if len(src) == 0 {
return cli.NewExitError(errNoInput, 1)
}
endpoint := ctx.String("endpoint")
if len(endpoint) == 0 {
return cli.NewExitError(errNoEndpoint, 1)
}
b, err := ioutil.ReadFile(src)
if err != nil {
@ -516,9 +505,12 @@ func testInvokeScript(ctx *cli.Context) error {
}
}
c, err := client.New(context.TODO(), endpoint, client.Options{})
gctx, cancel := options.GetTimeoutContext(ctx)
defer cancel()
c, err := options.GetRPCClient(gctx, ctx)
if err != nil {
return cli.NewExitError(err, 1)
return err
}
scriptHex := hex.EncodeToString(b)
@ -640,10 +632,6 @@ func contractDeploy(ctx *cli.Context) error {
if len(confFile) == 0 {
return cli.NewExitError(errNoConfFile, 1)
}
endpoint := ctx.String("endpoint")
if len(endpoint) == 0 {
return cli.NewExitError(errNoEndpoint, 1)
}
gas := flags.Fixed8FromContext(ctx, "gas")
acc, err := getAccFromContext(ctx)
@ -659,9 +647,12 @@ func contractDeploy(ctx *cli.Context) error {
return err
}
c, err := client.New(context.TODO(), endpoint, client.Options{})
gctx, cancel := options.GetTimeoutContext(ctx)
defer cancel()
c, err := options.GetRPCClient(gctx, ctx)
if err != nil {
return cli.NewExitError(err, 1)
return err
}
m := conf.ToManifest(avm)

View file

@ -5,31 +5,31 @@ import (
"fmt"
"io/ioutil"
"github.com/nspcc-dev/neo-go/cli/options"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/rpc/client"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/context"
"github.com/urfave/cli"
)
func newMultisigCommands() []cli.Command {
signFlags := []cli.Flag{
walletPathFlag,
outFlag,
inFlag,
cli.StringFlag{
Name: "addr",
Usage: "Address to use",
},
}
signFlags = append(signFlags, options.RPC...)
return []cli.Command{
{
Name: "sign",
Usage: "sign a transaction",
UsageText: "multisig sign --path <path> --addr <addr> --in <file.in> --out <file.out>",
Action: signMultisig,
Flags: []cli.Flag{
walletPathFlag,
rpcFlag,
timeoutFlag,
outFlag,
inFlag,
cli.StringFlag{
Name: "addr",
Usage: "Address to use",
},
},
Flags: signFlags,
},
}
}
@ -75,20 +75,21 @@ func signMultisig(ctx *cli.Context) error {
} else if err := writeParameterContext(c, ctx.String("out")); err != nil {
return cli.NewExitError(err, 1)
}
if endpoint := ctx.String("rpc"); endpoint != "" {
if len(ctx.String(options.RPCEndpointFlag)) != 0 {
w, err := c.GetWitness(acc.Contract)
if err != nil {
return cli.NewExitError(err, 1)
}
tx.Scripts = append(tx.Scripts, *w)
gctx, cancel := getGoContext(ctx)
gctx, cancel := options.GetTimeoutContext(ctx)
defer cancel()
c, err := client.New(gctx, ctx.String("rpc"), client.Options{})
c, err := options.GetRPCClient(gctx, ctx)
if err != nil {
return cli.NewExitError(err, 1)
} else if err := c.SendRawTransaction(tx); err != nil {
return err
}
if err := c.SendRawTransaction(tx); err != nil {
return cli.NewExitError(err, 1)
}
}

View file

@ -7,6 +7,7 @@ import (
"io/ioutil"
"github.com/nspcc-dev/neo-go/cli/flags"
"github.com/nspcc-dev/neo-go/cli/options"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/rpc/client"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/context"
@ -16,39 +17,59 @@ import (
)
func newNEP5Commands() []cli.Command {
balanceFlags := []cli.Flag{
walletPathFlag,
cli.StringFlag{
Name: "addr",
Usage: "Address to use",
},
cli.StringFlag{
Name: "token",
Usage: "Token to use",
},
}
balanceFlags = append(balanceFlags, options.RPC...)
importFlags := []cli.Flag{
walletPathFlag,
cli.StringFlag{
Name: "token",
Usage: "Token contract hash in LE",
},
}
importFlags = append(importFlags, options.RPC...)
transferFlags := []cli.Flag{
walletPathFlag,
outFlag,
fromAddrFlag,
toAddrFlag,
cli.StringFlag{
Name: "token",
Usage: "Token to use",
},
cli.StringFlag{
Name: "amount",
Usage: "Amount of asset to send",
},
flags.Fixed8Flag{
Name: "gas",
Usage: "Amount of GAS to attach to a tx",
},
}
transferFlags = append(transferFlags, options.RPC...)
return []cli.Command{
{
Name: "balance",
Usage: "get address balance",
UsageText: "balance --path <path> --rpc <node> --addr <addr> [--token <hash-or-name>]",
UsageText: "balance --path <path> --rpc-endpoint <node> --timeout <time> --addr <addr> [--token <hash-or-name>]",
Action: getNEP5Balance,
Flags: []cli.Flag{
walletPathFlag,
rpcFlag,
timeoutFlag,
cli.StringFlag{
Name: "addr",
Usage: "Address to use",
},
cli.StringFlag{
Name: "token",
Usage: "Token to use",
},
},
Flags: balanceFlags,
},
{
Name: "import",
Usage: "import NEP5 token to a wallet",
UsageText: "import --path <path> --rpc <node> --token <hash>",
UsageText: "import --path <path> --rpc-endpoint <node> --timeout <time> --token <hash>",
Action: importNEP5Token,
Flags: []cli.Flag{
walletPathFlag,
rpcFlag,
cli.StringFlag{
Name: "token",
Usage: "Token contract hash in LE",
},
},
Flags: importFlags,
},
{
Name: "info",
@ -80,28 +101,9 @@ func newNEP5Commands() []cli.Command {
{
Name: "transfer",
Usage: "transfer NEP5 tokens",
UsageText: "transfer --path <path> --rpc <node> --from <addr> --to <addr> --token <hash> --amount string",
UsageText: "transfer --path <path> --rpc-endpoint <node> --timeout <time> --from <addr> --to <addr> --token <hash> --amount string",
Action: transferNEP5,
Flags: []cli.Flag{
walletPathFlag,
rpcFlag,
outFlag,
timeoutFlag,
fromAddrFlag,
toAddrFlag,
cli.StringFlag{
Name: "token",
Usage: "Token to use",
},
cli.StringFlag{
Name: "amount",
Usage: "Amount of asset to send",
},
flags.Fixed8Flag{
Name: "gas",
Usage: "Amount of GAS to attach to a tx",
},
},
Flags: transferFlags,
},
}
}
@ -123,12 +125,12 @@ func getNEP5Balance(ctx *cli.Context) error {
return cli.NewExitError(fmt.Errorf("can't find account for the address: %s", addr), 1)
}
gctx, cancel := getGoContext(ctx)
gctx, cancel := options.GetTimeoutContext(ctx)
defer cancel()
c, err := client.New(gctx, ctx.String("rpc"), client.Options{})
c, err := options.GetRPCClient(gctx, ctx)
if err != nil {
return cli.NewExitError(err, 1)
return err
}
var token *wallet.Token
@ -218,12 +220,12 @@ func importNEP5Token(ctx *cli.Context) error {
}
}
gctx, cancel := getGoContext(ctx)
gctx, cancel := options.GetTimeoutContext(ctx)
defer cancel()
c, err := client.New(gctx, ctx.String("rpc"), client.Options{})
c, err := options.GetRPCClient(gctx, ctx)
if err != nil {
return cli.NewExitError(err, 1)
return err
}
tok, err := c.NEP5TokenInfo(tokenHash)
@ -314,11 +316,12 @@ func transferNEP5(ctx *cli.Context) error {
return cli.NewExitError(fmt.Errorf("can't find account for the address: %s", fromFlag), 1)
}
gctx, cancel := getGoContext(ctx)
gctx, cancel := options.GetTimeoutContext(ctx)
defer cancel()
c, err := client.New(gctx, ctx.String("rpc"), client.Options{})
c, err := options.GetRPCClient(gctx, ctx)
if err != nil {
return cli.NewExitError(err, 1)
return err
}
toFlag := ctx.Generic("to").(*flags.Address)

View file

@ -2,7 +2,6 @@ package wallet
import (
"bufio"
"context"
"encoding/hex"
"errors"
"fmt"
@ -11,9 +10,9 @@ import (
"syscall"
"github.com/nspcc-dev/neo-go/cli/flags"
"github.com/nspcc-dev/neo-go/cli/options"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/rpc/client"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/urfave/cli"
@ -38,14 +37,6 @@ var (
Name: "decrypt, d",
Usage: "Decrypt encrypted keys.",
}
rpcFlag = cli.StringFlag{
Name: "rpc, r",
Usage: "RPC node address",
}
timeoutFlag = cli.DurationFlag{
Name: "timeout, t",
Usage: "Timeout for the operation",
}
outFlag = cli.StringFlag{
Name: "out",
Usage: "file to put JSON transaction to",
@ -70,6 +61,14 @@ var (
// NewCommands returns 'wallet' command.
func NewCommands() []cli.Command {
claimFlags := []cli.Flag{
walletPathFlag,
flags.AddressFlag{
Name: "address, a",
Usage: "Address to claim GAS for",
},
}
claimFlags = append(claimFlags, options.RPC...)
return []cli.Command{{
Name: "wallet",
Usage: "create, open and manage a NEO wallet",
@ -78,15 +77,7 @@ func NewCommands() []cli.Command {
Name: "claim",
Usage: "claim GAS",
Action: claimGas,
Flags: []cli.Flag{
walletPathFlag,
rpcFlag,
timeoutFlag,
flags.AddressFlag{
Name: "address, a",
Usage: "Address to claim GAS for",
},
},
Flags: claimFlags,
},
{
Name: "init",
@ -223,12 +214,12 @@ func claimGas(ctx *cli.Context) error {
return cli.NewExitError(err, 1)
}
gctx, cancel := getGoContext(ctx)
gctx, cancel := options.GetTimeoutContext(ctx)
defer cancel()
c, err := client.New(gctx, ctx.String("rpc"), client.Options{})
c, err := options.GetRPCClient(gctx, ctx)
if err != nil {
return cli.NewExitError(err, 1)
return err
}
// Temporary.
neoHash, err := util.Uint160DecodeStringLE("3b7d3711c6f0ccf9b1dca903d1bfa1d896f1238c")
@ -476,13 +467,6 @@ func askForConsent() bool {
return false
}
func getGoContext(ctx *cli.Context) (context.Context, func()) {
if dur := ctx.Duration("timeout"); dur != 0 {
return context.WithTimeout(context.Background(), dur)
}
return context.Background(), func() {}
}
func dumpWallet(ctx *cli.Context) error {
wall, err := openWallet(ctx.String("path"))
if err != nil {

View file

@ -1,5 +1,5 @@
ProtocolConfiguration:
Magic: 56753
Magic: 42
SecondsPerBlock: 15
LowPriorityThreshold: 0.000
MemPoolSize: 50000

View file

@ -144,10 +144,10 @@ project:
It's passed to the `deploy` command via `-c` option:
```
$ ./bin/neo-go contract deploy -i contract.avm -c contract.yml -e http://localhost:20331 -w wallet.json -g 0.001
$ ./bin/neo-go contract deploy -i contract.avm -c contract.yml -r http://localhost:20331 -w wallet.json -g 0.001
```
Deployment works via an RPC server, an address of which is passed via `-e`
Deployment works via an RPC server, an address of which is passed via `-r`
option and should be signed using a wallet from `-w` option. More details can
be found in `deploy` command help.
@ -184,7 +184,7 @@ Example call (contract `f84d6a337fbc3d3a201d41da99e86b479e7a2554` with method
given RPC server and wallet and paying 0.00001 GAS for this transaction):
```
$ ./bin/neo-go contract invokefunction -e http://localhost:20331 -w my_wallet.json -g 0.00001 f84d6a337fbc3d3a201d41da99e86b479e7a2554 balanceOf AK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y
$ ./bin/neo-go contract invokefunction -r http://localhost:20331 -w my_wallet.json -g 0.00001 f84d6a337fbc3d3a201d41da99e86b479e7a2554 balanceOf AK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y
```
## Smart contract examples

View file

@ -5,6 +5,7 @@ import (
"testing"
"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core"
"github.com/nspcc-dev/neo-go/pkg/core/storage"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
@ -20,7 +21,7 @@ import (
// Benchmark test to measure number of processed TX.
// Same benchmark made on reference C# node https://github.com/neo-project/neo/issues/1321.
func BenchmarkTXPerformanceTest(t *testing.B) {
net := config.ModeUnitTestNet
net := netmode.UnitTestNet
configPath := "../config"
cfg, err := config.Load(configPath, net)
require.NoError(t, err, "could not load config")
@ -77,7 +78,7 @@ func getTX(t *testing.B, wif *keys.WIF) *transaction.Transaction {
fromAddressHash, err := address.StringToUint160(fromAddress)
require.NoError(t, err)
tx := transaction.New([]byte{0x51}, 1)
tx := transaction.New(netmode.UnitTestNet, []byte{0x51}, 1)
tx.Version = 0
tx.Sender = fromAddressHash
tx.Attributes = append(tx.Attributes,

View file

@ -7,6 +7,7 @@ import (
"testing"
"github.com/nspcc-dev/neo-go/pkg/compiler"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core"
"github.com/nspcc-dev/neo-go/pkg/core/dao"
"github.com/nspcc-dev/neo-go/pkg/core/interop"
@ -80,7 +81,7 @@ func TestAppCall(t *testing.T) {
inner, err := compiler.Compile(strings.NewReader(srcInner))
require.NoError(t, err)
ic := interop.NewContext(trigger.Application, nil, dao.NewSimple(storage.NewMemoryStore()), nil, nil, nil, zaptest.NewLogger(t))
ic := interop.NewContext(trigger.Application, nil, dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet), nil, nil, nil, zaptest.NewLogger(t))
require.NoError(t, ic.DAO.PutContractState(&state.Contract{Script: inner}))
ih := hash.Hash160(inner)

View file

@ -6,6 +6,7 @@ import (
"os"
"github.com/go-yaml/yaml"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/pkg/errors"
)
@ -28,7 +29,7 @@ func (c Config) GenerateUserAgent() string {
// Load attempts to load the config from the given
// path for the given netMode.
func Load(path string, netMode NetMode) (Config, error) {
func Load(path string, netMode netmode.Magic) (Config, error) {
configPath := fmt.Sprintf("%s/protocol.%s.yml", path, netMode)
if _, err := os.Stat(configPath); os.IsNotExist(err) {
return Config{}, errors.Wrap(err, "Unable to load config")

View file

@ -0,0 +1,33 @@
package netmode
import "strconv"
const (
// MainNet contains magic code used in the NEO main official network.
MainNet Magic = 0x004f454e // 5195086
// TestNet contains magic code used in the NEO testing network.
TestNet Magic = 0x744f454e // 1951352142
// PrivNet contains magic code usually used for NEO private networks.
PrivNet Magic = 56753 // docker privnet
// UnitTestNet is a stub magic code used for testing purposes.
UnitTestNet Magic = 42
)
// Magic describes the network the blockchain will operate on.
type Magic uint32
// String implements the stringer interface.
func (n Magic) String() string {
switch n {
case PrivNet:
return "privnet"
case TestNet:
return "testnet"
case MainNet:
return "mainnet"
case UnitTestNet:
return "unit_testnet"
default:
return "net 0x" + strconv.FormatUint(uint64(n), 16)
}
}

View file

@ -1,20 +1,10 @@
package config
import (
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/util"
)
const (
// ModeMainNet contains magic code used in the NEO main official network.
ModeMainNet NetMode = 0x00746e41 // 7630401
// ModeTestNet contains magic code used in the NEO testing network.
ModeTestNet NetMode = 0x74746e41 // 1953787457
// ModePrivNet contains magic code usually used for NEO private networks.
ModePrivNet NetMode = 56753 // docker privnet
// ModeUnitTestNet is a stub magic code used for testing purposes.
ModeUnitTestNet NetMode = 0
)
// ProtocolConfiguration represents the protocol config.
type (
ProtocolConfiguration struct {
@ -22,10 +12,10 @@ type (
// transactions exceeding the MaxFreeTransactionSize.
FeePerExtraByte float64 `yaml:"FeePerExtraByte"`
// FreeGasLimit is an amount of GAS which can be spent for free.
FreeGasLimit util.Fixed8 `yaml:"FreeGasLimit"`
LowPriorityThreshold float64 `yaml:"LowPriorityThreshold"`
Magic NetMode `yaml:"Magic"`
MaxTransactionsPerBlock int `yaml:"MaxTransactionsPerBlock"`
FreeGasLimit util.Fixed8 `yaml:"FreeGasLimit"`
LowPriorityThreshold float64 `yaml:"LowPriorityThreshold"`
Magic netmode.Magic `yaml:"Magic"`
MaxTransactionsPerBlock int `yaml:"MaxTransactionsPerBlock"`
// Maximum size of low priority transaction in bytes.
MaxFreeTransactionSize int `yaml:"MaxFreeTransactionSize"`
// Maximum number of low priority transactions accepted into block.
@ -41,23 +31,4 @@ type (
// Whether to verify transactions in received blocks.
VerifyTransactions bool `yaml:"VerifyTransactions"`
}
// NetMode describes the mode the blockchain will operate on.
NetMode uint32
)
// String implements the stringer interface.
func (n NetMode) String() string {
switch n {
case ModePrivNet:
return "privnet"
case ModeTestNet:
return "testnet"
case ModeMainNet:
return "mainnet"
case ModeUnitTestNet:
return "unit_testnet"
default:
return "net unknown"
}
}

View file

@ -6,6 +6,7 @@ import (
"github.com/nspcc-dev/dbft/block"
"github.com/nspcc-dev/dbft/crypto"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
@ -45,7 +46,7 @@ func TestNeoBlock_Setters(t *testing.T) {
b.Block.PrevHash = util.Uint256{9, 8, 7}
require.Equal(t, util.Uint256{9, 8, 7}, b.PrevHash())
txx := []block.Transaction{transaction.New([]byte{byte(opcode.PUSH1)}, 1)}
txx := []block.Transaction{transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 1)}
b.SetTransactions(txx)
require.Equal(t, txx, b.Transactions())
}

View file

@ -8,8 +8,8 @@ import (
"github.com/nspcc-dev/dbft"
"github.com/nspcc-dev/dbft/block"
"github.com/nspcc-dev/dbft/crypto"
"github.com/nspcc-dev/dbft/merkle"
"github.com/nspcc-dev/dbft/payload"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
coreb "github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/blockchainer"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
@ -61,6 +61,7 @@ type service struct {
blockEvents chan *coreb.Block
lastProposal []util.Uint256
wallet *wallet.Wallet
network netmode.Magic
}
// Config is a configuration for consensus services.
@ -101,6 +102,7 @@ func NewService(cfg Config) (Service, error) {
transactions: make(chan *transaction.Transaction, 100),
blockEvents: make(chan *coreb.Block, 1),
network: cfg.Chain.GetConfig().Magic,
}
if cfg.Wallet == nil {
@ -128,7 +130,7 @@ func NewService(cfg Config) (Service, error) {
dbft.WithVerifyBlock(srv.verifyBlock),
dbft.WithGetBlock(srv.getBlock),
dbft.WithWatchOnly(func() bool { return false }),
dbft.WithNewBlockFromContext(newBlockFromContext),
dbft.WithNewBlockFromContext(srv.newBlockFromContext),
dbft.WithCurrentHeight(cfg.Chain.BlockHeight),
dbft.WithCurrentBlockHash(cfg.Chain.CurrentBlockHash),
dbft.WithGetValidators(srv.getValidators),
@ -460,12 +462,13 @@ func convertKeys(validators []crypto.PublicKey) (pubs []*keys.PublicKey) {
return
}
func newBlockFromContext(ctx *dbft.Context) block.Block {
func (s *service) newBlockFromContext(ctx *dbft.Context) block.Block {
block := new(neoBlock)
if ctx.TransactionHashes == nil {
return nil
}
block.Block.Network = s.network
block.Block.Timestamp = ctx.Timestamp / 1000000
block.Block.Index = ctx.BlockIndex
block.Block.NextConsensus = ctx.NextConsensus
@ -475,12 +478,7 @@ func newBlockFromContext(ctx *dbft.Context) block.Block {
primaryIndex := uint32(ctx.PrimaryIndex)
block.Block.ConsensusData.PrimaryIndex = primaryIndex
consensusData := coreb.ConsensusData{
PrimaryIndex: primaryIndex,
Nonce: ctx.Nonce,
}
mt := merkle.NewMerkleTree(append([]util.Uint256{consensusData.Hash()}, ctx.TransactionHashes...)...)
block.Block.MerkleRoot = mt.Root().Hash
block.Block.RebuildMerkleRoot()
return block
}

View file

@ -6,6 +6,7 @@ import (
"github.com/nspcc-dev/dbft/block"
"github.com/nspcc-dev/dbft/payload"
"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core"
"github.com/nspcc-dev/neo-go/pkg/core/storage"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
@ -23,7 +24,7 @@ import (
func TestNewService(t *testing.T) {
srv := newTestService(t)
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx.ValidUntilBlock = 1
addSender(t, tx)
signTx(t, srv.Chain.FeePerByte(), tx)
@ -40,7 +41,7 @@ func TestService_GetVerified(t *testing.T) {
srv := newTestService(t)
var txs []*transaction.Transaction
for i := 0; i < 4; i++ {
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx.Nonce = 123 + uint32(i)
tx.ValidUntilBlock = 1
txs = append(txs, tx)
@ -54,7 +55,7 @@ func TestService_GetVerified(t *testing.T) {
p := new(Payload)
p.message = &message{}
p.SetType(payload.PrepareRequestType)
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx.Nonce = 999
p.SetPayload(&prepareRequest{transactionHashes: hashes})
p.SetValidatorIndex(1)
@ -121,7 +122,7 @@ func TestService_getTx(t *testing.T) {
srv := newTestService(t)
t.Run("transaction in mempool", func(t *testing.T) {
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx.Nonce = 1234
tx.ValidUntilBlock = 1
addSender(t, tx)
@ -138,7 +139,7 @@ func TestService_getTx(t *testing.T) {
})
t.Run("transaction in local cache", func(t *testing.T) {
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx.Nonce = 4321
tx.ValidUntilBlock = 1
h := tx.Hash()
@ -217,7 +218,7 @@ func getTestValidator(i int) (*privateKey, *publicKey) {
}
func newTestChain(t *testing.T) *core.Blockchain {
unitTestNetCfg, err := config.Load("../../config", config.ModeUnitTestNet)
unitTestNetCfg, err := config.Load("../../config", netmode.UnitTestNet)
require.NoError(t, err)
chain, err := core.NewBlockchain(storage.NewMemoryStore(), unitTestNetCfg.ProtocolConfiguration, zaptest.NewLogger(t))

View file

@ -5,6 +5,7 @@ import (
"errors"
"github.com/Workiva/go-datastructures/queue"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/io"
@ -26,12 +27,18 @@ type Block struct {
Trimmed bool
}
// auxBlock is used for JSON i/o.
type auxBlock struct {
// auxBlockOut is used for JSON i/o.
type auxBlockOut struct {
ConsensusData ConsensusData `json:"consensus_data"`
Transactions []*transaction.Transaction `json:"tx"`
}
// auxBlockIn is used for JSON i/o.
type auxBlockIn struct {
ConsensusData ConsensusData `json:"consensus_data"`
Transactions []json.RawMessage `json:"tx"`
}
// Header returns the Header of the Block.
func (b *Block) Header() *Header {
return &Header{
@ -88,8 +95,11 @@ func (b *Block) Verify() error {
// This is commonly used to create a block from stored data.
// Blocks created from trimmed data will have their Trimmed field
// set to true.
func NewBlockFromTrimmedBytes(b []byte) (*Block, error) {
func NewBlockFromTrimmedBytes(network netmode.Magic, b []byte) (*Block, error) {
block := &Block{
Base: Base{
Network: network,
},
Trimmed: true,
}
@ -117,6 +127,15 @@ func NewBlockFromTrimmedBytes(b []byte) (*Block, error) {
return block, br.Err
}
// New creates a new blank block tied to the specific network.
func New(network netmode.Magic) *Block {
return &Block{
Base: Base{
Network: network,
},
}
}
// Trim returns a subset of the block data to save up space
// in storage.
// Notice that only the hashes of the transactions are stored.
@ -155,7 +174,7 @@ func (b *Block) DecodeBinary(br *io.BinReader) {
b.ConsensusData.DecodeBinary(br)
txes := make([]*transaction.Transaction, contentsCount-1)
for i := 0; i < int(contentsCount)-1; i++ {
tx := new(transaction.Transaction)
tx := &transaction.Transaction{Network: b.Network}
tx.DecodeBinary(br)
txes[i] = tx
}
@ -192,7 +211,7 @@ func (b *Block) Compare(item queue.Item) int {
// MarshalJSON implements json.Marshaler interface.
func (b Block) MarshalJSON() ([]byte, error) {
auxb, err := json.Marshal(auxBlock{
auxb, err := json.Marshal(auxBlockOut{
ConsensusData: b.ConsensusData,
Transactions: b.Transactions,
})
@ -217,18 +236,26 @@ func (b Block) MarshalJSON() ([]byte, error) {
func (b *Block) UnmarshalJSON(data []byte) error {
// As Base and auxb are at the same level in json,
// do unmarshalling separately for both structs.
auxb := new(auxBlock)
auxb := new(auxBlockIn)
err := json.Unmarshal(data, auxb)
if err != nil {
return err
}
base := new(Base)
err = json.Unmarshal(data, base)
err = json.Unmarshal(data, &b.Base)
if err != nil {
return err
}
b.Base = *base
b.Transactions = auxb.Transactions
if len(auxb.Transactions) != 0 {
b.Transactions = make([]*transaction.Transaction, 0, len(auxb.Transactions))
for _, txBytes := range auxb.Transactions {
tx := &transaction.Transaction{Network: b.Network}
err = tx.UnmarshalJSON(txBytes)
if err != nil {
return err
}
b.Transactions = append(b.Transactions, tx)
}
}
b.ConsensusData = auxb.ConsensusData
// Some tests rely on hash presence and we're usually precomputing
// other hashes upon deserialization.

View file

@ -3,8 +3,8 @@ package block
import (
"encoding/json"
"errors"
"fmt"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
@ -35,12 +35,14 @@ type Base struct {
// Contract address of the next miner
NextConsensus util.Uint160
// Padding that is fixed to 1
_ uint8
// Script used to validate the block
Script transaction.Witness
// Network magic number this block belongs to. This one actually is not
// a part of the wire-representation of Block, but it's absolutely
// necessary for correct signing/verification.
Network netmode.Magic
// Hash of this block, created when binary encoded (double SHA256).
hash util.Uint256
@ -87,11 +89,9 @@ func (b *Base) VerificationHash() util.Uint256 {
// DecodeBinary implements Serializable interface.
func (b *Base) DecodeBinary(br *io.BinReader) {
b.decodeHashableFields(br)
padding := []byte{0}
br.ReadBytes(padding)
if padding[0] != 1 {
br.Err = fmt.Errorf("format error: padding must equal 1 got %d", padding)
witnessCount := br.ReadVarUint()
if br.Err == nil && witnessCount != 1 {
br.Err = errors.New("wrong witness count")
return
}
@ -101,13 +101,14 @@ func (b *Base) DecodeBinary(br *io.BinReader) {
// EncodeBinary implements Serializable interface
func (b *Base) EncodeBinary(bw *io.BinWriter) {
b.encodeHashableFields(bw)
bw.WriteBytes([]byte{1})
bw.WriteVarUint(1)
b.Script.EncodeBinary(bw)
}
// GetSignedPart returns serialized hashable data of the block.
func (b *Base) GetSignedPart() []byte {
buf := io.NewBufBinWriter()
buf.WriteU32LE(uint32(b.Network))
// No error can occure while encoding hashable fields.
b.encodeHashableFields(buf.BinWriter)

View file

@ -3,6 +3,7 @@ package block
import (
"testing"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
@ -85,7 +86,7 @@ func newDumbBlock() *Block {
Nonce: 1111,
},
Transactions: []*transaction.Transaction{
transaction.New([]byte{byte(opcode.PUSH1)}, 0),
transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0),
},
}
}

View file

@ -56,7 +56,7 @@ func (c *ConsensusData) createHash() error {
}
b := buf.Bytes()
c.hash = hash.Sha256(b)
c.hash = hash.DoubleSha256(b)
return nil
}

View file

@ -10,8 +10,6 @@ import (
type Header struct {
// Base of the block.
Base
// Padding that is fixed to 0.
_ uint8
}
// DecodeBinary implements Serializable interface.

View file

@ -170,7 +170,7 @@ func NewBlockchain(s storage.Store, cfg config.ProtocolConfiguration, log *zap.L
}
bc := &Blockchain{
config: cfg,
dao: dao.NewSimple(s),
dao: dao.NewSimple(s, cfg.Magic),
headersOp: make(chan headersOpFunc),
headersOpDone: make(chan struct{}),
stopCh: make(chan struct{}),

View file

@ -4,6 +4,7 @@ import (
"testing"
"time"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/storage"
@ -102,7 +103,7 @@ func TestScriptFromWitness(t *testing.T) {
func TestGetHeader(t *testing.T) {
bc := newTestChain(t)
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx.ValidUntilBlock = bc.BlockHeight() + 1
assert.Nil(t, addSender(tx))
assert.Nil(t, signTx(bc, tx))
@ -267,7 +268,7 @@ func TestSubscriptions(t *testing.T) {
emit.Bytes(script.BinWriter, []byte("yay!"))
emit.Syscall(script.BinWriter, "System.Runtime.Notify")
require.NoError(t, script.Err)
txGood1 := transaction.New(script.Bytes(), 0)
txGood1 := transaction.New(netmode.UnitTestNet, script.Bytes(), 0)
txGood1.Sender = neoOwner
txGood1.Nonce = 1
txGood1.ValidUntilBlock = 100500
@ -279,7 +280,7 @@ func TestSubscriptions(t *testing.T) {
emit.Syscall(script.BinWriter, "System.Runtime.Notify")
emit.Opcode(script.BinWriter, opcode.THROW)
require.NoError(t, script.Err)
txBad := transaction.New(script.Bytes(), 0)
txBad := transaction.New(netmode.UnitTestNet, script.Bytes(), 0)
txBad.Sender = neoOwner
txBad.Nonce = 2
txBad.ValidUntilBlock = 100500
@ -289,7 +290,7 @@ func TestSubscriptions(t *testing.T) {
emit.Bytes(script.BinWriter, []byte("yay! yay! yay!"))
emit.Syscall(script.BinWriter, "System.Runtime.Notify")
require.NoError(t, script.Err)
txGood2 := transaction.New(script.Bytes(), 0)
txGood2 := transaction.New(netmode.UnitTestNet, script.Bytes(), 0)
txGood2.Sender = neoOwner
txGood2.Nonce = 3
txGood2.ValidUntilBlock = 100500

View file

@ -3,6 +3,7 @@ package dao
import (
"testing"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/storage"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
@ -16,7 +17,7 @@ import (
func TestCachedDaoAccounts(t *testing.T) {
store := storage.NewMemoryStore()
// Persistent DAO to check for backing storage.
pdao := NewSimple(store)
pdao := NewSimple(store, netmode.UnitTestNet)
// Cached DAO.
cdao := NewCached(pdao)
@ -52,7 +53,7 @@ func TestCachedDaoAccounts(t *testing.T) {
func TestCachedDaoContracts(t *testing.T) {
store := storage.NewMemoryStore()
pdao := NewSimple(store)
pdao := NewSimple(store, netmode.UnitTestNet)
dao := NewCached(pdao)
script := []byte{0xde, 0xad, 0xbe, 0xef}
@ -97,7 +98,7 @@ func TestCachedDaoContracts(t *testing.T) {
func TestCachedCachedDao(t *testing.T) {
store := storage.NewMemoryStore()
// Persistent DAO to check for backing storage.
pdao := NewSimple(store)
pdao := NewSimple(store, netmode.UnitTestNet)
assert.NotEqual(t, store, pdao.Store)
// Cached DAO.
cdao := NewCached(pdao)

View file

@ -6,6 +6,7 @@ import (
"fmt"
"sort"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/storage"
@ -58,12 +59,13 @@ type DAO interface {
// Simple is memCached wrapper around DB, simple DAO implementation.
type Simple struct {
Store *storage.MemCachedStore
Store *storage.MemCachedStore
network netmode.Magic
}
// NewSimple creates new simple dao using provided backend store.
func NewSimple(backend storage.Store) *Simple {
return &Simple{Store: storage.NewMemCachedStore(backend)}
func NewSimple(backend storage.Store, network netmode.Magic) *Simple {
return &Simple{Store: storage.NewMemCachedStore(backend), network: network}
}
// GetBatch returns currently accumulated DB changeset.
@ -74,7 +76,7 @@ func (dao *Simple) GetBatch() *storage.MemBatch {
// GetWrapped returns new DAO instance with another layer of wrapped
// MemCachedStore around the current DAO Store.
func (dao *Simple) GetWrapped() DAO {
return NewSimple(dao.Store)
return NewSimple(dao.Store, dao.network)
}
// GetAndDecode performs get operation and decoding with serializable structures.
@ -376,7 +378,7 @@ func (dao *Simple) GetBlock(hash util.Uint256) (*block.Block, error) {
return nil, err
}
block, err := block.NewBlockFromTrimmedBytes(b)
block, err := block.NewBlockFromTrimmedBytes(dao.network, b)
if err != nil {
return nil, err
}
@ -455,7 +457,7 @@ func (dao *Simple) GetTransaction(hash util.Uint256) (*transaction.Transaction,
var height = r.ReadU32LE()
tx := &transaction.Transaction{}
tx := &transaction.Transaction{Network: dao.network}
tx.DecodeBinary(r)
if r.Err != nil {
return nil, 0, r.Err

View file

@ -3,6 +3,7 @@ package dao
import (
"testing"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/storage"
@ -15,7 +16,7 @@ import (
)
func TestPutGetAndDecode(t *testing.T) {
dao := NewSimple(storage.NewMemoryStore())
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet)
serializable := &TestSerializable{field: random.String(4)}
hash := []byte{1}
err := dao.Put(serializable, hash)
@ -40,7 +41,7 @@ func (t *TestSerializable) DecodeBinary(reader *io.BinReader) {
}
func TestGetAccountStateOrNew_New(t *testing.T) {
dao := NewSimple(storage.NewMemoryStore())
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet)
hash := random.Uint160()
createdAccount, err := dao.GetAccountStateOrNew(hash)
require.NoError(t, err)
@ -48,7 +49,7 @@ func TestGetAccountStateOrNew_New(t *testing.T) {
}
func TestPutAndGetAccountStateOrNew(t *testing.T) {
dao := NewSimple(storage.NewMemoryStore())
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet)
hash := random.Uint160()
accountState := &state.Account{ScriptHash: hash}
err := dao.PutAccountState(accountState)
@ -59,7 +60,7 @@ func TestPutAndGetAccountStateOrNew(t *testing.T) {
}
func TestPutAndGetContractState(t *testing.T) {
dao := NewSimple(storage.NewMemoryStore())
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet)
contractState := &state.Contract{Script: []byte{}}
hash := contractState.ScriptHash()
err := dao.PutContractState(contractState)
@ -70,7 +71,7 @@ func TestPutAndGetContractState(t *testing.T) {
}
func TestDeleteContractState(t *testing.T) {
dao := NewSimple(storage.NewMemoryStore())
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet)
contractState := &state.Contract{Script: []byte{}}
hash := contractState.ScriptHash()
err := dao.PutContractState(contractState)
@ -83,7 +84,7 @@ func TestDeleteContractState(t *testing.T) {
}
func TestSimple_GetNextContractID(t *testing.T) {
dao := NewSimple(storage.NewMemoryStore())
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet)
id, err := dao.GetNextContractID()
require.NoError(t, err)
require.EqualValues(t, 0, id)
@ -94,7 +95,7 @@ func TestSimple_GetNextContractID(t *testing.T) {
}
func TestPutGetAppExecResult(t *testing.T) {
dao := NewSimple(storage.NewMemoryStore())
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet)
hash := random.Uint256()
appExecResult := &state.AppExecResult{
TxHash: hash,
@ -109,7 +110,7 @@ func TestPutGetAppExecResult(t *testing.T) {
}
func TestPutGetStorageItem(t *testing.T) {
dao := NewSimple(storage.NewMemoryStore())
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet)
hash := random.Uint160()
key := []byte{0}
storageItem := &state.StorageItem{Value: []uint8{}}
@ -120,7 +121,7 @@ func TestPutGetStorageItem(t *testing.T) {
}
func TestDeleteStorageItem(t *testing.T) {
dao := NewSimple(storage.NewMemoryStore())
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet)
hash := random.Uint160()
key := []byte{0}
storageItem := &state.StorageItem{Value: []uint8{}}
@ -133,7 +134,7 @@ func TestDeleteStorageItem(t *testing.T) {
}
func TestGetBlock_NotExists(t *testing.T) {
dao := NewSimple(storage.NewMemoryStore())
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet)
hash := random.Uint256()
block, err := dao.GetBlock(hash)
require.Error(t, err)
@ -141,7 +142,7 @@ func TestGetBlock_NotExists(t *testing.T) {
}
func TestPutGetBlock(t *testing.T) {
dao := NewSimple(storage.NewMemoryStore())
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet)
b := &block.Block{
Base: block.Base{
Script: transaction.Witness{
@ -159,14 +160,14 @@ func TestPutGetBlock(t *testing.T) {
}
func TestGetVersion_NoVersion(t *testing.T) {
dao := NewSimple(storage.NewMemoryStore())
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet)
version, err := dao.GetVersion()
require.Error(t, err)
require.Equal(t, "", version)
}
func TestGetVersion(t *testing.T) {
dao := NewSimple(storage.NewMemoryStore())
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet)
err := dao.PutVersion("testVersion")
require.NoError(t, err)
version, err := dao.GetVersion()
@ -175,14 +176,14 @@ func TestGetVersion(t *testing.T) {
}
func TestGetCurrentHeaderHeight_NoHeader(t *testing.T) {
dao := NewSimple(storage.NewMemoryStore())
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet)
height, err := dao.GetCurrentBlockHeight()
require.Error(t, err)
require.Equal(t, uint32(0), height)
}
func TestGetCurrentHeaderHeight_Store(t *testing.T) {
dao := NewSimple(storage.NewMemoryStore())
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet)
b := &block.Block{
Base: block.Base{
Script: transaction.Witness{
@ -199,8 +200,8 @@ func TestGetCurrentHeaderHeight_Store(t *testing.T) {
}
func TestStoreAsTransaction(t *testing.T) {
dao := NewSimple(storage.NewMemoryStore())
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 1)
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet)
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 1)
hash := tx.Hash()
err := dao.StoreAsTransaction(tx, 0)
require.NoError(t, err)

View file

@ -34,7 +34,7 @@ var neoOwner = testchain.MultisigScriptHash()
// newTestChain should be called before newBlock invocation to properly setup
// global state.
func newTestChain(t *testing.T) *Blockchain {
unitTestNetCfg, err := config.Load("../../config", config.ModeUnitTestNet)
unitTestNetCfg, err := config.Load("../../config", testchain.Network())
require.NoError(t, err)
chain, err := NewBlockchain(storage.NewMemoryStore(), unitTestNetCfg.ProtocolConfiguration, zaptest.NewLogger(t))
require.NoError(t, err)
@ -59,6 +59,7 @@ func newBlock(cfg config.ProtocolConfiguration, index uint32, prev util.Uint256,
}
b := &block.Block{
Base: block.Base{
Network: testchain.Network(),
Version: 0,
PrevHash: prev,
Timestamp: uint64(time.Now().UTC().Unix())*1000 + uint64(index),
@ -102,7 +103,7 @@ func getDecodedBlock(t *testing.T, i int) *block.Block {
b, err := hex.DecodeString(data["raw"].(string))
require.NoError(t, err)
block := &block.Block{}
block := block.New(testchain.Network())
require.NoError(t, testserdes.DecodeBinary(b, block))
return block
@ -123,6 +124,7 @@ func getBlockData(i int) (map[string]interface{}, error) {
func newDumbBlock() *block.Block {
return &block.Block{
Base: block.Base{
Network: testchain.Network(),
Version: 0,
PrevHash: hash.Sha256([]byte("a")),
MerkleRoot: hash.Sha256([]byte("b")),
@ -139,7 +141,7 @@ func newDumbBlock() *block.Block {
Nonce: 1111,
},
Transactions: []*transaction.Transaction{
transaction.New([]byte{byte(opcode.PUSH1)}, 0),
transaction.New(testchain.Network(), []byte{byte(opcode.PUSH1)}, 0),
},
}
}
@ -240,7 +242,7 @@ func TestCreateBasicChain(t *testing.T) {
txScript := script.Bytes()
invFee := util.Fixed8FromFloat(100)
txDeploy := transaction.New(txScript, invFee)
txDeploy := transaction.New(testchain.Network(), txScript, invFee)
txDeploy.Nonce = getNextNonce()
txDeploy.ValidUntilBlock = validUntilBlock
txDeploy.Sender = priv0ScriptHash
@ -254,7 +256,7 @@ func TestCreateBasicChain(t *testing.T) {
script = io.NewBufBinWriter()
emit.AppCallWithOperationAndArgs(script.BinWriter, hash.Hash160(avm), "Put", "testkey", "testvalue")
txInv := transaction.New(script.Bytes(), 0)
txInv := transaction.New(testchain.Network(), script.Bytes(), 0)
txInv.Nonce = getNextNonce()
txInv.ValidUntilBlock = validUntilBlock
txInv.Sender = priv0ScriptHash
@ -285,7 +287,7 @@ func TestCreateBasicChain(t *testing.T) {
sh := hash.Hash160(avm)
w := io.NewBufBinWriter()
emit.AppCallWithOperationAndArgs(w.BinWriter, sh, "init")
initTx := transaction.New(w.Bytes(), 0)
initTx := transaction.New(testchain.Network(), w.Bytes(), 0)
initTx.Nonce = getNextNonce()
initTx.ValidUntilBlock = validUntilBlock
initTx.Sender = priv0ScriptHash
@ -375,7 +377,7 @@ func newNEP5Transfer(sc, from, to util.Uint160, amount int64) *transaction.Trans
emit.Opcode(w.BinWriter, opcode.ASSERT)
script := w.Bytes()
return transaction.New(script, 0)
return transaction.New(testchain.Network(), script, 0)
}
func addSender(txs ...*transaction.Transaction) error {

View file

@ -4,6 +4,7 @@ import (
"fmt"
"testing"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/dao"
"github.com/nspcc-dev/neo-go/pkg/core/interop"
@ -143,7 +144,7 @@ func TestECDSAVerify(t *testing.T) {
chain := newTestChain(t)
defer chain.Close()
ic := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore()), nil, nil)
ic := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet), nil, nil)
runCase := func(t *testing.T, isErr bool, result interface{}, args ...interface{}) {
v := vm.New()
for i := range args {
@ -177,14 +178,14 @@ func TestECDSAVerify(t *testing.T) {
})
t.Run("signed interop item", func(t *testing.T) {
tx := transaction.New([]byte{0, 1, 2}, 1)
tx := transaction.New(netmode.UnitTestNet, []byte{0, 1, 2}, 1)
msg := tx.GetSignedPart()
sign := priv.Sign(msg)
runCase(t, false, true, sign, priv.PublicKey().Bytes(), stackitem.NewInterop(tx))
})
t.Run("signed script container", func(t *testing.T) {
tx := transaction.New([]byte{0, 1, 2}, 1)
tx := transaction.New(netmode.UnitTestNet, []byte{0, 1, 2}, 1)
msg := tx.GetSignedPart()
sign := priv.Sign(msg)
ic.Container = tx
@ -218,7 +219,7 @@ func createVM(t *testing.T) (*vm.VM, *interop.Context, *Blockchain) {
v := vm.New()
chain := newTestChain(t)
context := chain.newInteropContext(trigger.Application,
dao.NewSimple(storage.NewMemoryStore()), nil, nil)
dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet), nil, nil)
return v, context, chain
}
@ -232,7 +233,7 @@ func createVMAndBlock(t *testing.T) (*vm.VM, *block.Block, *interop.Context, *Bl
v := vm.New()
block := newDumbBlock()
chain := newTestChain(t)
context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore()), block, nil)
context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet), block, nil)
return v, block, context, chain
}
@ -259,7 +260,7 @@ func createVMAndContractState(t *testing.T) (*vm.VM, *state.Contract, *interop.C
}
chain := newTestChain(t)
context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore()), nil, nil)
context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet), nil, nil)
return v, contractState, context, chain
}
@ -271,14 +272,14 @@ func createVMAndAccState(t *testing.T) (*vm.VM, *state.Account, *interop.Context
require.NoError(t, err)
chain := newTestChain(t)
context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore()), nil, nil)
context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet), nil, nil)
return v, accountState, context, chain
}
func createVMAndTX(t *testing.T) (*vm.VM, *transaction.Transaction, *interop.Context, *Blockchain) {
v := vm.New()
script := []byte{byte(opcode.PUSH1), byte(opcode.RET)}
tx := transaction.New(script, 0)
tx := transaction.New(netmode.UnitTestNet, script, 0)
bytes := make([]byte, 1)
attributes := append(tx.Attributes, transaction.Attribute{
@ -288,6 +289,6 @@ func createVMAndTX(t *testing.T) (*vm.VM, *transaction.Transaction, *interop.Con
tx.Attributes = attributes
chain := newTestChain(t)
context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore()), nil, tx)
context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet), nil, tx)
return v, tx, context, chain
}

View file

@ -5,6 +5,7 @@ import (
"runtime"
"testing"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/dao"
"github.com/nspcc-dev/neo-go/pkg/core/interop"
"github.com/nspcc-dev/neo-go/pkg/core/storage"
@ -18,7 +19,7 @@ func testNonInterop(t *testing.T, value interface{}, f func(*interop.Context, *v
v.Estack().PushVal(value)
chain := newTestChain(t)
defer chain.Close()
context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore()), nil, nil)
context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet), nil, nil)
require.Error(t, f(context, v))
}

View file

@ -4,6 +4,7 @@ import (
"sort"
"testing"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
@ -30,7 +31,7 @@ func (fs *FeerStub) GetUtilityTokenBalance(uint160 util.Uint160) util.Fixed8 {
func testMemPoolAddRemoveWithFeer(t *testing.T, fs Feer) {
mp := NewMemPool(10)
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx.Nonce = 0
_, ok := mp.TryGetValue(tx.Hash())
require.Equal(t, false, ok)
@ -61,7 +62,7 @@ func TestOverCapacity(t *testing.T) {
mp := NewMemPool(mempoolSize)
for i := 0; i < mempoolSize; i++ {
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx.Nonce = uint32(i)
require.NoError(t, mp.Add(tx, fs))
}
@ -71,7 +72,7 @@ func TestOverCapacity(t *testing.T) {
// Fees are also prioritized.
for i := 0; i < mempoolSize; i++ {
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx.Attributes = append(tx.Attributes, transaction.Attribute{
Usage: transaction.Hash1,
Data: util.Uint256{1, 2, 3, 4}.BytesBE(),
@ -85,7 +86,7 @@ func TestOverCapacity(t *testing.T) {
require.Equal(t, true, sort.IsSorted(sort.Reverse(mp.verifiedTxes)))
}
// Less prioritized txes are not allowed anymore.
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx.Attributes = append(tx.Attributes, transaction.Attribute{
Usage: transaction.Hash1,
Data: util.Uint256{1, 2, 3, 4}.BytesBE(),
@ -98,7 +99,7 @@ func TestOverCapacity(t *testing.T) {
require.Equal(t, true, sort.IsSorted(sort.Reverse(mp.verifiedTxes)))
// Low net fee, but higher per-byte fee is still a better combination.
tx = transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx = transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx.Nonce = txcnt
tx.NetworkFee = util.Fixed8FromFloat(0.00007)
txcnt++
@ -111,7 +112,7 @@ func TestOverCapacity(t *testing.T) {
// High priority always wins over low priority.
fs.lowPriority = false
for i := 0; i < mempoolSize; i++ {
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx.Nonce = txcnt
txcnt++
require.NoError(t, mp.Add(tx, fs))
@ -120,7 +121,7 @@ func TestOverCapacity(t *testing.T) {
}
// Good luck with low priority now.
fs.lowPriority = true
tx = transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx = transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx.Nonce = txcnt
require.Error(t, mp.Add(tx, fs))
require.Equal(t, mempoolSize, mp.Count())
@ -134,7 +135,7 @@ func TestGetVerified(t *testing.T) {
txes := make([]*transaction.Transaction, 0, mempoolSize)
for i := 0; i < mempoolSize; i++ {
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx.Nonce = uint32(i)
txes = append(txes, tx)
require.NoError(t, mp.Add(tx, fs))
@ -158,7 +159,7 @@ func TestRemoveStale(t *testing.T) {
txes1 := make([]*transaction.Transaction, 0, mempoolSize/2)
txes2 := make([]*transaction.Transaction, 0, mempoolSize/2)
for i := 0; i < mempoolSize; i++ {
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx.Nonce = uint32(i)
if i%2 == 0 {
txes1 = append(txes1, tx)
@ -187,7 +188,7 @@ func TestRemoveStale(t *testing.T) {
func TestMemPoolFees(t *testing.T) {
mp := NewMemPool(10)
sender0 := util.Uint160{1, 2, 3}
tx0 := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx0 := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx0.NetworkFee = util.Fixed8FromInt64(11000)
tx0.Sender = sender0
// insufficient funds to add transaction, but balance should be stored
@ -200,7 +201,7 @@ func TestMemPoolFees(t *testing.T) {
}, mp.fees[sender0])
// no problems with adding another transaction with lower fee
tx1 := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx1 := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx1.NetworkFee = util.Fixed8FromInt64(7000)
tx1.Sender = sender0
require.NoError(t, mp.Add(tx1, &FeerStub{}))
@ -211,7 +212,7 @@ func TestMemPoolFees(t *testing.T) {
}, mp.fees[sender0])
// balance shouldn't change after adding one more transaction
tx2 := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx2 := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx2.NetworkFee = util.Fixed8FromFloat(3000)
tx2.Sender = sender0
require.NoError(t, mp.Add(tx2, &FeerStub{}))
@ -223,7 +224,7 @@ func TestMemPoolFees(t *testing.T) {
}, mp.fees[sender0])
// can't add more transactions as we don't have enough GAS
tx3 := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx3 := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx3.NetworkFee = util.Fixed8FromFloat(0.5)
tx3.Sender = sender0
require.Equal(t, false, mp.Verify(tx3, &FeerStub{}))

View file

@ -92,7 +92,7 @@ func TestNativeContract_Invoke(t *testing.T) {
w := io.NewBufBinWriter()
emit.AppCallWithOperationAndArgs(w.BinWriter, tn.Metadata().Hash, "sum", int64(14), int64(28))
script := w.Bytes()
tx := transaction.New(script, 0)
tx := transaction.New(chain.GetConfig().Magic, script, 0)
validUntil := chain.blockHeight + 1
tx.ValidUntilBlock = validUntil
require.NoError(t, addSender(tx))

View file

@ -4,6 +4,7 @@ import (
"encoding/hex"
"testing"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/stretchr/testify/assert"
)
@ -16,7 +17,7 @@ var (
func decodeTransaction(rawTX string, t *testing.T) *Transaction {
b, err1 := hex.DecodeString(rawTX)
assert.Nil(t, err1)
tx, err := NewTransactionFromBytes(b)
tx, err := NewTransactionFromBytes(netmode.UnitTestNet, b)
assert.NoError(t, err)
return tx
}

View file

@ -5,6 +5,7 @@ import (
"errors"
"math/rand"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/io"
@ -58,6 +59,11 @@ type Transaction struct {
// and invocation script.
Scripts []Witness
// Network magic number. This one actually is not a part of the
// wire-representation of Transaction, but it's absolutely necessary
// for correct signing/verification.
Network netmode.Magic
// Hash of the transaction (double SHA256).
hash util.Uint256
@ -80,7 +86,7 @@ func NewTrimmedTX(hash util.Uint256) *Transaction {
// New returns a new transaction to execute given script and pay given system
// fee.
func New(script []byte, gas util.Fixed8) *Transaction {
func New(network netmode.Magic, script []byte, gas util.Fixed8) *Transaction {
return &Transaction{
Version: 0,
Nonce: rand.Uint32(),
@ -89,6 +95,7 @@ func New(script []byte, gas util.Fixed8) *Transaction {
Attributes: []Attribute{},
Cosigners: []Cosigner{},
Scripts: []Witness{},
Network: network,
}
}
@ -112,8 +119,9 @@ func (t *Transaction) VerificationHash() util.Uint256 {
return t.verificationHash
}
// DecodeBinary implements Serializable interface.
func (t *Transaction) DecodeBinary(br *io.BinReader) {
// decodeHashableFields decodes the fields that are used for signing the
// transaction, which are all fields except the scripts.
func (t *Transaction) decodeHashableFields(br *io.BinReader) {
t.Version = uint8(br.ReadB())
if t.Version > 0 {
br.Err = errors.New("only version 0 is supported")
@ -154,7 +162,14 @@ func (t *Transaction) DecodeBinary(br *io.BinReader) {
br.Err = errors.New("no script")
return
}
}
// DecodeBinary implements Serializable interface.
func (t *Transaction) DecodeBinary(br *io.BinReader) {
t.decodeHashableFields(br)
if br.Err != nil {
return
}
br.ReadArray(&t.Scripts)
// Create the hash of the transaction at decode, so we dont need
@ -195,22 +210,25 @@ func (t *Transaction) encodeHashableFields(bw *io.BinWriter) {
// createHash creates the hash of the transaction.
func (t *Transaction) createHash() error {
buf := io.NewBufBinWriter()
t.encodeHashableFields(buf.BinWriter)
if buf.Err != nil {
return buf.Err
b := t.GetSignedPart()
if b == nil {
return errors.New("failed to serialize hashable data")
}
t.updateHashes(b)
return nil
}
b := buf.Bytes()
// updateHashes updates Transaction's hashes based on the given buffer which should
// be a signable data slice.
func (t *Transaction) updateHashes(b []byte) {
t.verificationHash = hash.Sha256(b)
t.hash = hash.Sha256(t.verificationHash.BytesBE())
return nil
}
// GetSignedPart returns a part of the transaction which must be signed.
func (t *Transaction) GetSignedPart() []byte {
buf := io.NewBufBinWriter()
buf.WriteU32LE(uint32(t.Network))
t.encodeHashableFields(buf.BinWriter)
if buf.Err != nil {
return nil
@ -218,6 +236,24 @@ func (t *Transaction) GetSignedPart() []byte {
return buf.Bytes()
}
// DecodeSignedPart decodes a part of transaction from GetSignedPart data.
func (t *Transaction) DecodeSignedPart(buf []byte) error {
r := io.NewBinReaderFromBuf(buf)
t.Network = netmode.Magic(r.ReadU32LE())
t.decodeHashableFields(r)
if r.Err != nil {
return r.Err
}
// Ensure all the data was read.
_ = r.ReadB()
if r.Err == nil {
return errors.New("additional data after the signed part")
}
t.Scripts = make([]Witness, 0)
t.updateHashes(buf)
return nil
}
// Bytes converts the transaction to []byte
func (t *Transaction) Bytes() []byte {
buf := io.NewBufBinWriter()
@ -229,8 +265,8 @@ func (t *Transaction) Bytes() []byte {
}
// NewTransactionFromBytes decodes byte array into *Transaction
func NewTransactionFromBytes(b []byte) (*Transaction, error) {
tx := &Transaction{}
func NewTransactionFromBytes(network netmode.Magic, b []byte) (*Transaction, error) {
tx := &Transaction{Network: network}
r := io.NewBinReaderFromBuf(b)
tx.DecodeBinary(r)
if r.Err != nil {

View file

@ -4,6 +4,7 @@ import (
"encoding/hex"
"testing"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/internal/testserdes"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/stretchr/testify/assert"
@ -63,12 +64,12 @@ func TestDecodeEncodeInvocationTX(t *testing.T) {
func TestNew(t *testing.T) {
script := []byte{0x51}
tx := New(script, 1)
tx := New(netmode.UnitTestNet, script, 1)
assert.Equal(t, util.Fixed8(1), tx.SystemFee)
assert.Equal(t, script, tx.Script)
// Update hash fields to match tx2 that is gonna autoupdate them on decode.
_ = tx.Hash()
testserdes.EncodeDecodeBinary(t, tx, new(Transaction))
testserdes.EncodeDecodeBinary(t, tx, &Transaction{Network: netmode.UnitTestNet})
}
func TestEncodingTXWithNoScript(t *testing.T) {

View file

@ -4,6 +4,7 @@ import (
"time"
"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
@ -53,12 +54,13 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error)
InvocationScript: []byte{},
VerificationScript: []byte{byte(opcode.PUSH1)},
},
Network: cfg.Magic,
}
b := &block.Block{
Base: base,
Transactions: []*transaction.Transaction{
deployNativeContracts(),
deployNativeContracts(cfg.Magic),
},
ConsensusData: block.ConsensusData{
PrimaryIndex: 0,
@ -73,11 +75,11 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error)
return b, nil
}
func deployNativeContracts() *transaction.Transaction {
func deployNativeContracts(magic netmode.Magic) *transaction.Transaction {
buf := io.NewBufBinWriter()
emit.Syscall(buf.BinWriter, "Neo.Native.Deploy")
script := buf.Bytes()
tx := transaction.New(script, 0)
tx := transaction.New(magic, script, 0)
tx.Nonce = 0
tx.Sender = hash.Hash160([]byte{byte(opcode.PUSH1)})
tx.Scripts = []transaction.Witness{

View file

@ -4,13 +4,14 @@ import (
"testing"
"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGenesisBlockMainNet(t *testing.T) {
cfg, err := config.Load("../../config", config.ModeMainNet)
cfg, err := config.Load("../../config", netmode.MainNet)
require.NoError(t, err)
block, err := createGenesisBlock(cfg.ProtocolConfiguration)
@ -20,7 +21,7 @@ func TestGenesisBlockMainNet(t *testing.T) {
// have been changed. Consequently, hash of the genesis block has been changed.
// Update expected genesis block hash for better times.
// Old hash is "d42561e3d30e15be6400b6df2f328e02d2bf6354c41dce433bc57687c82144bf"
expect := "e4cfc549c87d4ab7b570c368d05853ffb70eb9ef0f7d9c7a2e6e9e5d713ebbf4"
expect := "dba446947a90b2862ef050703b44828ad8b02d11978f8ef59bd3e1c97aabf6e5"
assert.Equal(t, expect, block.Hash().StringLE())
}
@ -30,7 +31,7 @@ func TestGetConsensusAddressMainNet(t *testing.T) {
consensusScript = "72c3d9b3bbf776698694cd2c73fa597a10c31294"
)
cfg, err := config.Load("../../config", config.ModeMainNet)
cfg, err := config.Load("../../config", netmode.MainNet)
require.NoError(t, err)
validators, err := getValidators(cfg.ProtocolConfiguration)

View file

@ -4,3 +4,10 @@ package crypto
type Verifiable interface {
GetSignedPart() []byte
}
// VerifiableDecodable represents an object which can be both verified and
// decoded from given data.
type VerifiableDecodable interface {
Verifiable
DecodeSignedPart([]byte) error
}

View file

@ -0,0 +1,8 @@
package testchain
import "github.com/nspcc-dev/neo-go/pkg/config/netmode"
// Network returns test chain network's magic number.
func Network() netmode.Magic {
return netmode.UnitTestNet
}

View file

@ -1,33 +1,29 @@
package network
import (
"bytes"
"io"
"github.com/pierrec/lz4"
)
// compress compresses bytes using lz4.
func compress(source []byte) ([]byte, error) {
dest := new(bytes.Buffer)
w := lz4.NewWriter(dest)
_, err := io.Copy(w, bytes.NewReader(source))
dest := make([]byte, lz4.CompressBlockBound(len(source)))
size, err := lz4.CompressBlock(source, dest, nil)
if err != nil {
return nil, err
}
if w.Close() != nil {
return nil, err
}
return dest.Bytes(), nil
return dest[:size], nil
}
// decompress decompresses bytes using lz4.
func decompress(source []byte) ([]byte, error) {
dest := new(bytes.Buffer)
r := lz4.NewReader(bytes.NewReader(source))
_, err := io.Copy(dest, r)
maxSize := len(source) * 255
if maxSize > PayloadMaxSize {
maxSize = PayloadMaxSize
}
dest := make([]byte, maxSize)
size, err := lz4.UncompressBlock(source, dest)
if err != nil {
return nil, err
}
return dest.Bytes(), nil
return dest[:size], nil
}

View file

@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/consensus"
"github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
@ -33,6 +34,10 @@ type Message struct {
// Compressed message payload.
compressedPayload []byte
// Network this message comes from, it has to be set upon Message
// creation for correct decoding.
Network netmode.Magic
}
// MessageFlag represents compression level of message payload
@ -40,8 +45,8 @@ type MessageFlag byte
// Possible message flags
const (
None MessageFlag = 0
Compressed MessageFlag = 1 << iota
None MessageFlag = 0
)
// CommandType represents the type of a message command.
@ -83,7 +88,8 @@ const (
CMDAlert CommandType = 0x40
)
// NewMessage returns a new message with the given payload.
// NewMessage returns a new message with the given payload. It's intended to be
// used for messages to be sent, thus it doesn't care much about the Network.
func NewMessage(cmd CommandType, p payload.Payload) *Message {
return &Message{
Command: cmd,
@ -103,14 +109,14 @@ func (m *Message) Decode(br *io.BinReader) error {
m.Payload = payload.NewNullPayload()
return nil
}
if l > PayloadMaxSize {
return errors.New("invalid payload size")
}
m.compressedPayload = make([]byte, l)
br.ReadBytes(m.compressedPayload)
if br.Err != nil {
return br.Err
}
if len(m.compressedPayload) > PayloadMaxSize {
return errors.New("invalid payload size")
}
return m.decodePayload()
}
@ -135,7 +141,7 @@ func (m *Message) decodePayload() error {
case CMDAddr:
p = &payload.AddressList{}
case CMDBlock:
p = &block.Block{}
p = block.New(m.Network)
case CMDConsensus:
p = &consensus.Payload{}
case CMDGetBlocks:
@ -145,9 +151,9 @@ func (m *Message) decodePayload() error {
case CMDGetBlockData:
p = &payload.GetBlockData{}
case CMDHeaders:
p = &payload.Headers{}
p = &payload.Headers{Network: m.Network}
case CMDTX:
p = &transaction.Transaction{}
p = &transaction.Transaction{Network: m.Network}
case CMDMerkleBlock:
p = &payload.MerkleBlock{}
case CMDPing, CMDPong:

View file

@ -1,6 +1,7 @@
package payload
import (
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/pkg/errors"
@ -8,7 +9,8 @@ import (
// Headers payload.
type Headers struct {
Hdrs []*block.Header
Hdrs []*block.Header
Network netmode.Magic
}
// Users can at most request 2k header.
@ -34,6 +36,7 @@ func (p *Headers) DecodeBinary(br *io.BinReader) {
for i := 0; i < int(lenHeaders); i++ {
header := &block.Header{}
header.Network = p.Network
header.DecodeBinary(br)
p.Hdrs[i] = header
}

View file

@ -3,7 +3,7 @@ package payload
import (
"time"
"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/network/capability"
)
@ -11,7 +11,7 @@ import (
// Version payload.
type Version struct {
// NetMode of the node
Magic config.NetMode
Magic netmode.Magic
// currently the version of the protocol is 0
Version uint32
// timestamp
@ -25,7 +25,7 @@ type Version struct {
}
// NewVersion returns a pointer to a Version payload.
func NewVersion(magic config.NetMode, id uint32, ua string, c []capability.Capability) *Version {
func NewVersion(magic netmode.Magic, id uint32, ua string, c []capability.Capability) *Version {
return &Version{
Magic: magic,
Version: 0,
@ -38,7 +38,7 @@ func NewVersion(magic config.NetMode, id uint32, ua string, c []capability.Capab
// DecodeBinary implements Serializable interface.
func (p *Version) DecodeBinary(br *io.BinReader) {
p.Magic = config.NetMode(br.ReadU32LE())
p.Magic = netmode.Magic(br.ReadU32LE())
p.Version = br.ReadU32LE()
p.Timestamp = br.ReadU32LE()
p.Nonce = br.ReadU32LE()

View file

@ -3,14 +3,14 @@ package payload
import (
"testing"
"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/internal/testserdes"
"github.com/nspcc-dev/neo-go/pkg/network/capability"
"github.com/stretchr/testify/assert"
)
func TestVersionEncodeDecode(t *testing.T) {
var magic config.NetMode = 56753
var magic netmode.Magic = 56753
var tcpPort uint16 = 3000
var wsPort uint16 = 3001
var id uint32 = 13337

View file

@ -10,6 +10,7 @@ import (
"sync"
"time"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/consensus"
"github.com/nspcc-dev/neo-go/pkg/core"
"github.com/nspcc-dev/neo-go/pkg/core/block"
@ -53,6 +54,9 @@ type (
// id also known as the nonce of the server.
id uint32
// Network's magic number for correct message decoding.
network netmode.Magic
transport Transporter
discovery Discoverer
chain blockchainer.Blockchainer
@ -95,6 +99,7 @@ func NewServer(config ServerConfig, chain blockchainer.Blockchainer, log *zap.Lo
ServerConfig: config,
chain: chain,
id: randomID(),
network: chain.GetConfig().Magic,
quit: make(chan struct{}),
register: make(chan Peer),
unregister: make(chan peerDrop),

View file

@ -4,6 +4,7 @@ import (
"time"
"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/wallet"
"go.uber.org/zap/zapcore"
)
@ -38,7 +39,7 @@ type (
// ModePrivNet docker private network.
// ModeTestNet NEO test network.
// ModeMainNet NEO main network.
Net config.NetMode
Net netmode.Magic
// Relay determines whether the server is forwarding its inventory.
Relay bool

View file

@ -150,7 +150,7 @@ func (p *TCPPeer) handleConn() {
if err == nil {
r := io.NewBinReaderFromIO(p.conn)
for {
msg := &Message{}
msg := &Message{Network: p.server.network}
err = msg.Decode(r)
if err == payload.ErrTooManyHeaders {

View file

@ -11,6 +11,7 @@ import (
"sync"
"time"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
"github.com/nspcc-dev/neo-go/pkg/rpc/response"
@ -49,6 +50,7 @@ type Options struct {
CACert string
DialTimeout time.Duration
RequestTimeout time.Duration
Network netmode.Magic
}
// cache stores cache values for the RPC client methods

View file

@ -5,13 +5,14 @@ import (
"fmt"
"os"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/rpc/client"
)
func Example() {
endpoint := "http://seed5.bridgeprotocol.io:10332"
opts := client.Options{}
opts := client.Options{Network: netmode.MainNet}
c, err := client.New(context.TODO(), endpoint, opts)
if err != nil {

View file

@ -109,7 +109,7 @@ func (c *Client) CreateNEP5TransferTx(acc *wallet.Account, to util.Uint160, toke
emit.Opcode(w.BinWriter, opcode.ASSERT)
script := w.Bytes()
tx := transaction.New(script, gas)
tx := transaction.New(c.opts.Network, script, gas)
tx.Sender = from
tx.Cosigners = []transaction.Cosigner{
{

View file

@ -72,7 +72,7 @@ func (c *Client) getBlock(params request.RawParams) (*block.Block, error) {
return nil, err
}
r := io.NewBinReaderFromBuf(blockBytes)
b = new(block.Block)
b = block.New(c.opts.Network)
b.DecodeBinary(r)
if r.Err != nil {
return nil, r.Err
@ -98,6 +98,7 @@ func (c *Client) getBlockVerbose(params request.RawParams) (*result.Block, error
resp = &result.Block{}
err error
)
resp.Network = c.opts.Network
if err = c.performRequest("getblock", params, resp); err != nil {
return nil, err
}
@ -133,6 +134,7 @@ func (c *Client) GetBlockHeader(hash util.Uint256) (*block.Header, error) {
}
r := io.NewBinReaderFromBuf(headerBytes)
h = new(block.Header)
h.Network = c.opts.Network
h.DecodeBinary(r)
if r.Err != nil {
return nil, r.Err
@ -247,7 +249,7 @@ func (c *Client) GetRawTransaction(hash util.Uint256) (*transaction.Transaction,
if err != nil {
return nil, err
}
tx, err := transaction.NewTransactionFromBytes(txBytes)
tx, err := transaction.NewTransactionFromBytes(c.opts.Network, txBytes)
if err != nil {
return nil, err
}
@ -263,6 +265,7 @@ func (c *Client) GetRawTransactionVerbose(hash util.Uint256) (*result.Transactio
resp = &result.TransactionOutputRaw{}
err error
)
resp.Network = c.opts.Network
if err = c.performRequest("getrawtransaction", params, resp); err != nil {
return nil, err
}
@ -421,7 +424,7 @@ func (c *Client) SignAndPushInvocationTx(script []byte, acc *wallet.Account, sys
var txHash util.Uint256
var err error
tx := transaction.New(script, sysfee)
tx := transaction.New(c.opts.Network, script, sysfee)
tx.SystemFee = sysfee
validUntilBlock, err := c.CalculateValidUntilBlock()

View file

@ -11,6 +11,7 @@ import (
"time"
"github.com/gorilla/websocket"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
@ -35,17 +36,17 @@ type rpcClientTestCase struct {
check func(t *testing.T, c *Client, result interface{})
}
const hexB1 = "00000000e862e7907fc987cd58ddb3abb754aeb8812c9377c45e737a036fe88a622c3b8f301f2e84a86b207270830e7929530ccb841a3df7379fe6f0ac8865b33316839501cdd0847201000001000000abec5362f11e75b6e02e407bb98d63675d14384101fd08010c40ab634ce91590e77b246cee8b204e8a270268ee1ef32434cece73f425a7dbc90f1bed1dbe914edcaa2653167ad170ae10e16a9b2c6b7e0af1f711fb848fbb1b7f0c40232de6ad07ee3846bafa96302d37602349501a556df575e7df0743e45b076d6a0c6c6dd4cad3898f9e8848dd054abd303b229fd12984042f241f0e668f39a0fb0c408b4af43057df189a9d471010b5150bab442040403147c5e502bda38cde3ff8bce803f01245e07e2bfb95d57349c55dcc27e3710b82f2735d0f40eb4342908e330c40cda66f743d4ed8d856f5376953f9169581c668a9370245aef16202ebef9bb3f7f81234be62ec287d701ad7d8bf5042648019af9fe5baa0a8e05d279bfdb1d4c994130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb030057040000000000000002000000abec5362f11e75b6e02e407bb98d63675d14384100000000000000003e5f0d0000000000b00400000001abec5362f11e75b6e02e407bb98d63675d14384101590218ddf5050c14316e851039019d39dfc2c37d6c3fee19fd5809870c14abec5362f11e75b6e02e407bb98d63675d14384113c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b523801fd08010c402d96d8fde4ba266f89bc71ef117361967e0d11ed84cd60942a27bc99994dc58adf36a0e74ce976aac657a87a3c19c38e8ca450c67420046b81d98c60fd8feb040c40b3c15d5d23e0403a36cf559caee2979ca6ef00fe255df0e5c3daac4da051016b41eba42668934cd3308359451bafdd5419d059179fd40859684a3b91388bf9d80c407ac048cf8540b091955a374a0f36dae560c92c0134886507a589edf58b9dfbb4e3dbd5450be34e269d2e5454eb14eb7d6280d6101b4529410f829d37634849be0c403bba4113a687ff8507c1753f8519557531cf9df51ecc20deeb2c2b003ec5a1f7588cdd50b99e40b4f8039bb56c5df7ec9e7d6ea4b02fe23792510da21c7557f394130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb0003000000abec5362f11e75b6e02e407bb98d63675d1438410000000000000000de6e0d0000000000b00400000001abec5362f11e75b6e02e407bb98d63675d143841015d0300e87648170000000c14316e851039019d39dfc2c37d6c3fee19fd5809870c14abec5362f11e75b6e02e407bb98d63675d14384113c00c087472616e736665720c143b7d3711c6f0ccf9b1dca903d1bfa1d896f1238c41627d5b523801fd08010c4063fb12aa9f3fb83f6324ea9c7ec11fa9e995b51140f480409d68cf4d625e598b0632d6610602984bfa2f5e5ea9bcc62a0e6d818dd271b38530c0d1b8a71b4e0c0c4013e091eac6f304668d647c5c032fd1020597ea5204545e21c38655a6343d58492118f1231ede91af848af7e1d987d1a8816966f5fc1a7821c6c6f62734267bde0c40daadd04a7a4141d96c58de2d373e672ca071e2b82138ef52df016ac522710385db2ac73743d2fe73061fa5d6cb0ff73a7ec7f0667e4c8bff6aa0d5783128d36e0c40dab85cd87d3f92be9532292bdc6f420b0ecbf2f877c70c6a9921ee0fc900dfc53998cf020a51fa9af3d0608f6a2b9048cea3c0b586485802bbd278b261eee8a494130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"
const hexB1 = "000000008aaab19c43c4ca2870c3e616b123f1b689866f44b138ae4d6a5352e54442fd56401107247de4e35599d1feffaf6e763972f738d2858b0a22ad06523867e4dcf921f7c1c67201000001000000abec5362f11e75b6e02e407bb98d63675d14384101fd08010c400f01eb6371a135527ddb205a0dae1f69d2d324837cce128bead9033091883f9ce21e6d759a40f690746592b021d397f088e3b7b417fcef73cd1bfdc2800769520c4084f7ae5d9f58a09aa56eeb2f282744a59a82d17e3be0eb1c7f54e6e8df79620e2608191bac57280a836db2ec2a776d07e43f16bc76c47d348b0fcd09d56c7c320c402b95b4e39ec35162a640795ff223e92dec95390a072eb457f6a4323052f80731517e0df029e4a457204f777f5261c6a4a88d46d4c3abdec635a6eed580d6c77f0c40b9735745b1dd795a258c31d8e6fa87d5cfc2e9b3a4890d610d33bcf833b64c58b0c5cea17f3a7128f1065ed193e636971590f193f28bdd1eeebbbc1fe6e7cee594130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb030057040000000000000002000000abec5362f11e75b6e02e407bb98d63675d14384100000000000000003e5f0d0000000000b00400000001abec5362f11e75b6e02e407bb98d63675d14384101590218ddf5050c14316e851039019d39dfc2c37d6c3fee19fd5809870c14abec5362f11e75b6e02e407bb98d63675d14384113c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b523801fd08010c40ae6fc04fe4b6c22218ca9617c98d607d9ec9b1faf8cfdc3391bec485ae76b11adc6cc6abeb31a50b536ea8073e674d62a5566fce5e0a0ceb0718cb971c1ae3d00c40603071b725a58d052cad7afd88e99b27baab931afd5bb50d16e224335aab450170aabe251d3c0c6ad3f31dd7e9b89b209baabe5a1e2fa588bd8118f9e2a6960f0c40d72afcf39e663dba2d70fb8c36a09d1a6a6ad0d2fd38c857a8e7dc71e2b98711324e0d2ec641fe6896ba63ba80d3ea341c1aad11e082fb188ee07e215b4031b10c409afb2808b60286a56343b7ffcef28bb2ab0c595603e7323b5e5b0b9c1c10edfa5c40754d921865cb6fd71668a206b37a1eb10c0029a9fcd3a856aed07742cd3f94130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb0003000000abec5362f11e75b6e02e407bb98d63675d1438410000000000000000de6e0d0000000000b00400000001abec5362f11e75b6e02e407bb98d63675d143841015d0300e87648170000000c14316e851039019d39dfc2c37d6c3fee19fd5809870c14abec5362f11e75b6e02e407bb98d63675d14384113c00c087472616e736665720c143b7d3711c6f0ccf9b1dca903d1bfa1d896f1238c41627d5b523801fd08010c408710e7b5d8ac6cd8d09d6fb35bf2dcce5f5fb38595ddb6d04a570bc925bc2c55a73cdf5f3cb5a1feb0acc4f26c8bbca6c43df3b4a98b8c3c2c809c2f096eb25a0c40c186c102cbf72313fd94df5077fc5bbefcd32227ed2159a47a46594877fa39f330d8223b45aa24aff005bebb5b2427a50c8c4de8618e7d7b00d73d836c44942e0c40a243b5b565bd4bc2f0bb112f7624f6b3514c12413c5a95230819face3f760f03fcb96b188f98038a3f251686b53a88d69744f4e4a985e6297003a80cdb169e800c404a951e61ac99d5ee31831d111754adb711b4a9060a9524fe383a90771843cdb096382674027a87f2a15a83bd77deb2b2ab1fe8b3de6e546293ef3df9b1129e2894130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"
const hexTxMoveNeo = "0002000000abec5362f11e75b6e02e407bb98d63675d14384100000000000000003e5f0d0000000000b00400000001abec5362f11e75b6e02e407bb98d63675d14384101590218ddf5050c14316e851039019d39dfc2c37d6c3fee19fd5809870c14abec5362f11e75b6e02e407bb98d63675d14384113c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b523801fd08010c402d96d8fde4ba266f89bc71ef117361967e0d11ed84cd60942a27bc99994dc58adf36a0e74ce976aac657a87a3c19c38e8ca450c67420046b81d98c60fd8feb040c40b3c15d5d23e0403a36cf559caee2979ca6ef00fe255df0e5c3daac4da051016b41eba42668934cd3308359451bafdd5419d059179fd40859684a3b91388bf9d80c407ac048cf8540b091955a374a0f36dae560c92c0134886507a589edf58b9dfbb4e3dbd5450be34e269d2e5454eb14eb7d6280d6101b4529410f829d37634849be0c403bba4113a687ff8507c1753f8519557531cf9df51ecc20deeb2c2b003ec5a1f7588cdd50b99e40b4f8039bb56c5df7ec9e7d6ea4b02fe23792510da21c7557f394130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"
const hexTxMoveNeo = "0002000000abec5362f11e75b6e02e407bb98d63675d14384100000000000000003e5f0d0000000000b00400000001abec5362f11e75b6e02e407bb98d63675d14384101590218ddf5050c14316e851039019d39dfc2c37d6c3fee19fd5809870c14abec5362f11e75b6e02e407bb98d63675d14384113c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b523801fd08010c40ae6fc04fe4b6c22218ca9617c98d607d9ec9b1faf8cfdc3391bec485ae76b11adc6cc6abeb31a50b536ea8073e674d62a5566fce5e0a0ceb0718cb971c1ae3d00c40603071b725a58d052cad7afd88e99b27baab931afd5bb50d16e224335aab450170aabe251d3c0c6ad3f31dd7e9b89b209baabe5a1e2fa588bd8118f9e2a6960f0c40d72afcf39e663dba2d70fb8c36a09d1a6a6ad0d2fd38c857a8e7dc71e2b98711324e0d2ec641fe6896ba63ba80d3ea341c1aad11e082fb188ee07e215b4031b10c409afb2808b60286a56343b7ffcef28bb2ab0c595603e7323b5e5b0b9c1c10edfa5c40754d921865cb6fd71668a206b37a1eb10c0029a9fcd3a856aed07742cd3f94130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb"
const b1Verbose = `{"id":5,"jsonrpc":"2.0","result":{"size":1681,"nextblockhash":"0xf2afe371a27c9dbac4f4a8ad8eba750898b7c04aa298e64fe9e488e947976045","confirmations":6,"hash":"0xbd178d8d4a28ec082c034f817ce2423221281a31e7e00014dbf732c4053033d2","version":0,"previousblockhash":"0x8f3b2c628ae86f037a735ec477932c81b8ae54b7abb3dd58cd87c97f90e762e8","merkleroot":"0x95831633b36588acf0e69f37f73d1a84cb0c5329790e837072206ba8842e1f30","time":1591366176001,"index":1,"nextconsensus":"Nbb1qkwcwNSBs9pAnrVVrnFbWnbWBk91U2","witnesses":[{"invocation":"DECrY0zpFZDneyRs7osgToonAmjuHvMkNM7Oc/Qlp9vJDxvtHb6RTtyqJlMWetFwrhDhapssa34K8fcR+4SPuxt/DEAjLeatB+44Rrr6ljAtN2AjSVAaVW31deffB0PkWwdtagxsbdTK04mPnohI3QVKvTA7Ip/RKYQELyQfDmaPOaD7DECLSvQwV98Ymp1HEBC1FQurRCBAQDFHxeUCvaOM3j/4vOgD8BJF4H4r+5XVc0nFXcwn43ELgvJzXQ9A60NCkI4zDEDNpm90PU7Y2Fb1N2lT+RaVgcZoqTcCRa7xYgLr75uz9/gSNL5i7Ch9cBrX2L9QQmSAGa+f5bqgqOBdJ5v9sdTJ","verification":"EwwhAhA6f33QFlWFl/eWDSfFFqQ5T9loueZRVetLAT5AQEBuDCECp7xV/oaE4BGXaNEEujB5W9zIZhnoZK3SYVZyPtGFzWIMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwgwhA9kMB99j5pDOd5EuEKtRrMlEtmhgI3tgjE+PgwnnHuaZFAtBMHOzuw=="}],"consensus_data":{"primary":0,"nonce":"0000000000000457"},"tx":[{"txid":"0x8af9ccb8e7e0f0a73e77b78dc52750e77c50f78b09ecc2f0669c0b459cc7dd89","size":575,"version":0,"nonce":2,"sender":"Nbb1qkwcwNSBs9pAnrVVrnFbWnbWBk91U2","sys_fee":"0","net_fee":"0.0087635","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x4138145d67638db97b402ee0b6751ef16253ecab","scopes":"CalledByEntry"}],"script":"Ahjd9QUMFDFuhRA5AZ0538LDfWw/7hn9WAmHDBSr7FNi8R51tuAuQHu5jWNnXRQ4QRPADAh0cmFuc2ZlcgwUiXcg2M129PAKv6N8Dt2InCCP3ptBYn1bUjg=","scripts":[{"invocation":"DEAtltj95Lomb4m8ce8Rc2GWfg0R7YTNYJQqJ7yZmU3Fit82oOdM6XaqxleoejwZw46MpFDGdCAEa4HZjGD9j+sEDECzwV1dI+BAOjbPVZyu4pecpu8A/iVd8OXD2qxNoFEBa0HrpCZok0zTMINZRRuv3VQZ0FkXn9QIWWhKO5E4i/nYDEB6wEjPhUCwkZVaN0oPNtrlYMksATSIZQelie31i537tOPb1UUL404mnS5UVOsU631igNYQG0UpQQ+CnTdjSEm+DEA7ukETpof/hQfBdT+FGVV1Mc+d9R7MIN7rLCsAPsWh91iM3VC5nkC0+AObtWxd9+yefW6ksC/iN5JRDaIcdVfz","verification":"EwwhAhA6f33QFlWFl/eWDSfFFqQ5T9loueZRVetLAT5AQEBuDCECp7xV/oaE4BGXaNEEujB5W9zIZhnoZK3SYVZyPtGFzWIMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwgwhA9kMB99j5pDOd5EuEKtRrMlEtmhgI3tgjE+PgwnnHuaZFAtBMHOzuw=="}]},{"txid":"0xe7cff9e4820e53232dae619a3e6f57a9430dc240b5ed7b5c0ea2cfee3e90c985","size":579,"version":0,"nonce":3,"sender":"Nbb1qkwcwNSBs9pAnrVVrnFbWnbWBk91U2","sys_fee":"0","net_fee":"0.0088035","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x4138145d67638db97b402ee0b6751ef16253ecab","scopes":"CalledByEntry"}],"script":"AwDodkgXAAAADBQxboUQOQGdOd/Cw31sP+4Z/VgJhwwUq+xTYvEedbbgLkB7uY1jZ10UOEETwAwIdHJhbnNmZXIMFDt9NxHG8Mz5sdypA9G/odiW8SOMQWJ9W1I4","scripts":[{"invocation":"DEBj+xKqnz+4P2Mk6px+wR+p6ZW1EUD0gECdaM9NYl5ZiwYy1mEGAphL+i9eXqm8xioObYGN0nGzhTDA0binG04MDEAT4JHqxvMEZo1kfFwDL9ECBZfqUgRUXiHDhlWmND1YSSEY8SMe3pGvhIr34dmH0aiBaWb1/Bp4IcbG9ic0JnveDEDardBKekFB2WxY3i03PmcsoHHiuCE471LfAWrFInEDhdsqxzdD0v5zBh+l1ssP9zp+x/BmfkyL/2qg1XgxKNNuDEDauFzYfT+SvpUyKSvcb0ILDsvy+HfHDGqZIe4PyQDfxTmYzwIKUfqa89Bgj2orkEjOo8C1hkhYArvSeLJh7uik","verification":"EwwhAhA6f33QFlWFl/eWDSfFFqQ5T9loueZRVetLAT5AQEBuDCECp7xV/oaE4BGXaNEEujB5W9zIZhnoZK3SYVZyPtGFzWIMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwgwhA9kMB99j5pDOd5EuEKtRrMlEtmhgI3tgjE+PgwnnHuaZFAtBMHOzuw=="}]}]}}`
const b1Verbose = `{"id":5,"jsonrpc":"2.0","result":{"size":1681,"nextblockhash":"0x45f62d72e37b074ecdc9f687222b0f91ec98d6d9af4429a2caa2e076a9196b0d","confirmations":6,"hash":"0x4f2c5539b0213ea444608cc217c5cb191255c1858ccd051ad9a36f08df26a288","version":0,"previousblockhash":"0x56fd4244e552536a4dae38b1446f8689b6f123b116e6c37028cac4439cb1aa8a","merkleroot":"0xf9dce467385206ad220a8b85d238f77239766eaffffed19955e3e47d24071140","time":1592472500001,"index":1,"nextconsensus":"Nbb1qkwcwNSBs9pAnrVVrnFbWnbWBk91U2","witnesses":[{"invocation":"DEAPAetjcaE1Un3bIFoNrh9p0tMkg3zOEovq2QMwkYg/nOIebXWaQPaQdGWSsCHTl/CI47e0F/zvc80b/cKAB2lSDECE965dn1igmqVu6y8oJ0SlmoLRfjvg6xx/VObo33liDiYIGRusVygKg22y7Cp3bQfkPxa8dsR9NIsPzQnVbHwyDEArlbTjnsNRYqZAeV/yI+kt7JU5CgcutFf2pDIwUvgHMVF+DfAp5KRXIE93f1JhxqSojUbUw6vexjWm7tWA1sd/DEC5c1dFsd15WiWMMdjm+ofVz8Lps6SJDWENM7z4M7ZMWLDFzqF/OnEo8QZe0ZPmNpcVkPGT8ovdHu67vB/m587l","verification":"EwwhAhA6f33QFlWFl/eWDSfFFqQ5T9loueZRVetLAT5AQEBuDCECp7xV/oaE4BGXaNEEujB5W9zIZhnoZK3SYVZyPtGFzWIMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwgwhA9kMB99j5pDOd5EuEKtRrMlEtmhgI3tgjE+PgwnnHuaZFAtBMHOzuw=="}],"consensus_data":{"primary":0,"nonce":"0000000000000457"},"tx":[{"txid":"0x7fb05b593cf4b1eb2d9a283c5488ca1bfe61191b5775bafa43b8647e7b20f22c","size":575,"version":0,"nonce":2,"sender":"Nbb1qkwcwNSBs9pAnrVVrnFbWnbWBk91U2","sys_fee":"0","net_fee":"0.0087635","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x4138145d67638db97b402ee0b6751ef16253ecab","scopes":"CalledByEntry"}],"script":"Ahjd9QUMFDFuhRA5AZ0538LDfWw/7hn9WAmHDBSr7FNi8R51tuAuQHu5jWNnXRQ4QRPADAh0cmFuc2ZlcgwUiXcg2M129PAKv6N8Dt2InCCP3ptBYn1bUjg=","scripts":[{"invocation":"DECub8BP5LbCIhjKlhfJjWB9nsmx+vjP3DORvsSFrnaxGtxsxqvrMaULU26oBz5nTWKlVm/OXgoM6wcYy5ccGuPQDEBgMHG3JaWNBSytev2I6ZsnuquTGv1btQ0W4iQzWqtFAXCqviUdPAxq0/Md1+m4myCbqr5aHi+liL2BGPnippYPDEDXKvzznmY9ui1w+4w2oJ0aamrQ0v04yFeo59xx4rmHETJODS7GQf5olrpjuoDT6jQcGq0R4IL7GI7gfiFbQDGxDECa+ygItgKGpWNDt//O8ouyqwxZVgPnMjteWwucHBDt+lxAdU2SGGXLb9cWaKIGs3oesQwAKan806hWrtB3Qs0/","verification":"EwwhAhA6f33QFlWFl/eWDSfFFqQ5T9loueZRVetLAT5AQEBuDCECp7xV/oaE4BGXaNEEujB5W9zIZhnoZK3SYVZyPtGFzWIMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwgwhA9kMB99j5pDOd5EuEKtRrMlEtmhgI3tgjE+PgwnnHuaZFAtBMHOzuw=="}]},{"txid":"0xb661d5e4d9e41c3059b068f8abb6f1566a47ec800879e34c0ebd2799781a2760","size":579,"version":0,"nonce":3,"sender":"Nbb1qkwcwNSBs9pAnrVVrnFbWnbWBk91U2","sys_fee":"0","net_fee":"0.0088035","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x4138145d67638db97b402ee0b6751ef16253ecab","scopes":"CalledByEntry"}],"script":"AwDodkgXAAAADBQxboUQOQGdOd/Cw31sP+4Z/VgJhwwUq+xTYvEedbbgLkB7uY1jZ10UOEETwAwIdHJhbnNmZXIMFDt9NxHG8Mz5sdypA9G/odiW8SOMQWJ9W1I4","scripts":[{"invocation":"DECHEOe12Kxs2NCdb7Nb8tzOX1+zhZXdttBKVwvJJbwsVac83188taH+sKzE8myLvKbEPfO0qYuMPCyAnC8JbrJaDEDBhsECy/cjE/2U31B3/Fu+/NMiJ+0hWaR6RllId/o58zDYIjtFqiSv8AW+u1skJ6UMjE3oYY59ewDXPYNsRJQuDECiQ7W1Zb1LwvC7ES92JPazUUwSQTxalSMIGfrOP3YPA/y5axiPmAOKPyUWhrU6iNaXRPTkqYXmKXADqAzbFp6ADEBKlR5hrJnV7jGDHREXVK23EbSpBgqVJP44OpB3GEPNsJY4JnQCeofyoVqDvXfesrKrH+iz3m5UYpPvPfmxEp4o","verification":"EwwhAhA6f33QFlWFl/eWDSfFFqQ5T9loueZRVetLAT5AQEBuDCECp7xV/oaE4BGXaNEEujB5W9zIZhnoZK3SYVZyPtGFzWIMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwgwhA9kMB99j5pDOd5EuEKtRrMlEtmhgI3tgjE+PgwnnHuaZFAtBMHOzuw=="}]}]}}`
const hexHeader1 = "00000000e862e7907fc987cd58ddb3abb754aeb8812c9377c45e737a036fe88a622c3b8f301f2e84a86b207270830e7929530ccb841a3df7379fe6f0ac8865b33316839501cdd0847201000001000000abec5362f11e75b6e02e407bb98d63675d14384101fd08010c40ab634ce91590e77b246cee8b204e8a270268ee1ef32434cece73f425a7dbc90f1bed1dbe914edcaa2653167ad170ae10e16a9b2c6b7e0af1f711fb848fbb1b7f0c40232de6ad07ee3846bafa96302d37602349501a556df575e7df0743e45b076d6a0c6c6dd4cad3898f9e8848dd054abd303b229fd12984042f241f0e668f39a0fb0c408b4af43057df189a9d471010b5150bab442040403147c5e502bda38cde3ff8bce803f01245e07e2bfb95d57349c55dcc27e3710b82f2735d0f40eb4342908e330c40cda66f743d4ed8d856f5376953f9169581c668a9370245aef16202ebef9bb3f7f81234be62ec287d701ad7d8bf5042648019af9fe5baa0a8e05d279bfdb1d4c994130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb00"
const hexHeader1 = "000000008aaab19c43c4ca2870c3e616b123f1b689866f44b138ae4d6a5352e54442fd56401107247de4e35599d1feffaf6e763972f738d2858b0a22ad06523867e4dcf921f7c1c67201000001000000abec5362f11e75b6e02e407bb98d63675d14384101fd08010c400f01eb6371a135527ddb205a0dae1f69d2d324837cce128bead9033091883f9ce21e6d759a40f690746592b021d397f088e3b7b417fcef73cd1bfdc2800769520c4084f7ae5d9f58a09aa56eeb2f282744a59a82d17e3be0eb1c7f54e6e8df79620e2608191bac57280a836db2ec2a776d07e43f16bc76c47d348b0fcd09d56c7c320c402b95b4e39ec35162a640795ff223e92dec95390a072eb457f6a4323052f80731517e0df029e4a457204f777f5261c6a4a88d46d4c3abdec635a6eed580d6c77f0c40b9735745b1dd795a258c31d8e6fa87d5cfc2e9b3a4890d610d33bcf833b64c58b0c5cea17f3a7128f1065ed193e636971590f193f28bdd1eeebbbc1fe6e7cee594130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb00"
const header1Verbose = `{"id":5,"jsonrpc":"2.0","result":{"hash":"0xbd178d8d4a28ec082c034f817ce2423221281a31e7e00014dbf732c4053033d2","size":518,"version":0,"previousblockhash":"0x8f3b2c628ae86f037a735ec477932c81b8ae54b7abb3dd58cd87c97f90e762e8","merkleroot":"0x95831633b36588acf0e69f37f73d1a84cb0c5329790e837072206ba8842e1f30","time":1591366176001,"index":1,"nextconsensus":"Nbb1qkwcwNSBs9pAnrVVrnFbWnbWBk91U2","witnesses":[{"invocation":"DECrY0zpFZDneyRs7osgToonAmjuHvMkNM7Oc/Qlp9vJDxvtHb6RTtyqJlMWetFwrhDhapssa34K8fcR+4SPuxt/DEAjLeatB+44Rrr6ljAtN2AjSVAaVW31deffB0PkWwdtagxsbdTK04mPnohI3QVKvTA7Ip/RKYQELyQfDmaPOaD7DECLSvQwV98Ymp1HEBC1FQurRCBAQDFHxeUCvaOM3j/4vOgD8BJF4H4r+5XVc0nFXcwn43ELgvJzXQ9A60NCkI4zDEDNpm90PU7Y2Fb1N2lT+RaVgcZoqTcCRa7xYgLr75uz9/gSNL5i7Ch9cBrX2L9QQmSAGa+f5bqgqOBdJ5v9sdTJ","verification":"EwwhAhA6f33QFlWFl/eWDSfFFqQ5T9loueZRVetLAT5AQEBuDCECp7xV/oaE4BGXaNEEujB5W9zIZhnoZK3SYVZyPtGFzWIMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwgwhA9kMB99j5pDOd5EuEKtRrMlEtmhgI3tgjE+PgwnnHuaZFAtBMHOzuw=="}],"confirmations":6,"nextblockhash":"0xf2afe371a27c9dbac4f4a8ad8eba750898b7c04aa298e64fe9e488e947976045"}}`
const header1Verbose = `{"id":5,"jsonrpc":"2.0","result":{"hash":"0x4f2c5539b0213ea444608cc217c5cb191255c1858ccd051ad9a36f08df26a288","size":518,"version":0,"previousblockhash":"0x56fd4244e552536a4dae38b1446f8689b6f123b116e6c37028cac4439cb1aa8a","merkleroot":"0xf9dce467385206ad220a8b85d238f77239766eaffffed19955e3e47d24071140","time":1592472500001,"index":1,"nextconsensus":"Nbb1qkwcwNSBs9pAnrVVrnFbWnbWBk91U2","witnesses":[{"invocation":"DEAPAetjcaE1Un3bIFoNrh9p0tMkg3zOEovq2QMwkYg/nOIebXWaQPaQdGWSsCHTl/CI47e0F/zvc80b/cKAB2lSDECE965dn1igmqVu6y8oJ0SlmoLRfjvg6xx/VObo33liDiYIGRusVygKg22y7Cp3bQfkPxa8dsR9NIsPzQnVbHwyDEArlbTjnsNRYqZAeV/yI+kt7JU5CgcutFf2pDIwUvgHMVF+DfAp5KRXIE93f1JhxqSojUbUw6vexjWm7tWA1sd/DEC5c1dFsd15WiWMMdjm+ofVz8Lps6SJDWENM7z4M7ZMWLDFzqF/OnEo8QZe0ZPmNpcVkPGT8ovdHu67vB/m587l","verification":"EwwhAhA6f33QFlWFl/eWDSfFFqQ5T9loueZRVetLAT5AQEBuDCECp7xV/oaE4BGXaNEEujB5W9zIZhnoZK3SYVZyPtGFzWIMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwgwhA9kMB99j5pDOd5EuEKtRrMlEtmhgI3tgjE+PgwnnHuaZFAtBMHOzuw=="}],"confirmations":6,"nextblockhash":"0x45f62d72e37b074ecdc9f687222b0f91ec98d6d9af4429a2caa2e076a9196b0d"}}`
const txMoveNeoVerbose = `{"id":5,"jsonrpc":"2.0","result":{"blockhash":"0xbd178d8d4a28ec082c034f817ce2423221281a31e7e00014dbf732c4053033d2","confirmations":6,"blocktime":1591366176001,"txid":"0x8af9ccb8e7e0f0a73e77b78dc52750e77c50f78b09ecc2f0669c0b459cc7dd89","size":575,"version":0,"nonce":2,"sender":"Nbb1qkwcwNSBs9pAnrVVrnFbWnbWBk91U2","sys_fee":"0","net_fee":"0.0087635","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x4138145d67638db97b402ee0b6751ef16253ecab","scopes":"CalledByEntry"}],"script":"Ahjd9QUMFDFuhRA5AZ0538LDfWw/7hn9WAmHDBSr7FNi8R51tuAuQHu5jWNnXRQ4QRPADAh0cmFuc2ZlcgwUiXcg2M129PAKv6N8Dt2InCCP3ptBYn1bUjg=","scripts":[{"invocation":"DEAtltj95Lomb4m8ce8Rc2GWfg0R7YTNYJQqJ7yZmU3Fit82oOdM6XaqxleoejwZw46MpFDGdCAEa4HZjGD9j+sEDECzwV1dI+BAOjbPVZyu4pecpu8A/iVd8OXD2qxNoFEBa0HrpCZok0zTMINZRRuv3VQZ0FkXn9QIWWhKO5E4i/nYDEB6wEjPhUCwkZVaN0oPNtrlYMksATSIZQelie31i537tOPb1UUL404mnS5UVOsU631igNYQG0UpQQ+CnTdjSEm+DEA7ukETpof/hQfBdT+FGVV1Mc+d9R7MIN7rLCsAPsWh91iM3VC5nkC0+AObtWxd9+yefW6ksC/iN5JRDaIcdVfz","verification":"EwwhAhA6f33QFlWFl/eWDSfFFqQ5T9loueZRVetLAT5AQEBuDCECp7xV/oaE4BGXaNEEujB5W9zIZhnoZK3SYVZyPtGFzWIMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwgwhA9kMB99j5pDOd5EuEKtRrMlEtmhgI3tgjE+PgwnnHuaZFAtBMHOzuw=="}]}}`
const txMoveNeoVerbose = `{"id":5,"jsonrpc":"2.0","result":{"blockhash":"0x4f2c5539b0213ea444608cc217c5cb191255c1858ccd051ad9a36f08df26a288","confirmations":6,"blocktime":1592472500001,"txid":"0x7fb05b593cf4b1eb2d9a283c5488ca1bfe61191b5775bafa43b8647e7b20f22c","size":575,"version":0,"nonce":2,"sender":"Nbb1qkwcwNSBs9pAnrVVrnFbWnbWBk91U2","sys_fee":"0","net_fee":"0.0087635","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x4138145d67638db97b402ee0b6751ef16253ecab","scopes":"CalledByEntry"}],"script":"Ahjd9QUMFDFuhRA5AZ0538LDfWw/7hn9WAmHDBSr7FNi8R51tuAuQHu5jWNnXRQ4QRPADAh0cmFuc2ZlcgwUiXcg2M129PAKv6N8Dt2InCCP3ptBYn1bUjg=","scripts":[{"invocation":"DECub8BP5LbCIhjKlhfJjWB9nsmx+vjP3DORvsSFrnaxGtxsxqvrMaULU26oBz5nTWKlVm/OXgoM6wcYy5ccGuPQDEBgMHG3JaWNBSytev2I6ZsnuquTGv1btQ0W4iQzWqtFAXCqviUdPAxq0/Md1+m4myCbqr5aHi+liL2BGPnippYPDEDXKvzznmY9ui1w+4w2oJ0aamrQ0v04yFeo59xx4rmHETJODS7GQf5olrpjuoDT6jQcGq0R4IL7GI7gfiFbQDGxDECa+ygItgKGpWNDt//O8ouyqwxZVgPnMjteWwucHBDt+lxAdU2SGGXLb9cWaKIGs3oesQwAKan806hWrtB3Qs0/","verification":"EwwhAhA6f33QFlWFl/eWDSfFFqQ5T9loueZRVetLAT5AQEBuDCECp7xV/oaE4BGXaNEEujB5W9zIZhnoZK3SYVZyPtGFzWIMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwgwhA9kMB99j5pDOd5EuEKtRrMlEtmhgI3tgjE+PgwnnHuaZFAtBMHOzuw=="}]}}`
// getResultBlock1 returns data for block number 1 which is used by several tests.
func getResultBlock1() *result.Block {
@ -53,17 +54,17 @@ func getResultBlock1() *result.Block {
if err != nil {
panic(err)
}
b := new(block.Block)
b := block.New(netmode.UnitTestNet)
err = testserdes.DecodeBinary(binB, b)
if err != nil {
panic(err)
}
b2Hash, err := util.Uint256DecodeStringLE("f2afe371a27c9dbac4f4a8ad8eba750898b7c04aa298e64fe9e488e947976045")
b2Hash, err := util.Uint256DecodeStringLE("45f62d72e37b074ecdc9f687222b0f91ec98d6d9af4429a2caa2e076a9196b0d")
if err != nil {
panic(err)
}
return &result.Block{
Block: b,
Block: *b,
BlockMetadata: result.BlockMetadata{
Size: 1681,
NextBlockHash: &b2Hash,
@ -78,13 +79,12 @@ func getTxMoveNeo() *result.TransactionOutputRaw {
if err != nil {
panic(err)
}
tx := new(transaction.Transaction)
err = testserdes.DecodeBinary(txBin, tx)
tx, err := transaction.NewTransactionFromBytes(netmode.UnitTestNet, txBin)
if err != nil {
panic(err)
}
return &result.TransactionOutputRaw{
Transaction: tx,
Transaction: *tx,
TransactionMetadata: result.TransactionMetadata{
Timestamp: b1.Timestamp,
Blockhash: b1.Block.Hash(),
@ -154,7 +154,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"` + hexB1 + `"}`,
result: func(c *Client) interface{} {
b := getResultBlock1()
return b.Block
return &b.Block
},
},
{
@ -179,7 +179,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"` + hexB1 + `"}`,
result: func(c *Client) interface{} {
b := getResultBlock1()
return b.Block
return &b.Block
},
},
{
@ -448,7 +448,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"` + hexTxMoveNeo + `"}`,
result: func(c *Client) interface{} {
tx := getTxMoveNeo()
return tx.Transaction
return &tx.Transaction
},
},
{
@ -619,7 +619,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
{
name: "positive",
invoke: func(c *Client) (interface{}, error) {
return nil, c.SendRawTransaction(transaction.New([]byte{byte(opcode.PUSH1)}, 0))
return nil, c.SendRawTransaction(transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0))
},
serverResponse: `{"jsonrpc":"2.0","id":1,"result":true}`,
result: func(c *Client) interface{} {
@ -740,7 +740,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{
{
name: "sendrawtransaction_bad_server_answer",
invoke: func(c *Client) (interface{}, error) {
return nil, c.SendRawTransaction(transaction.New([]byte{byte(opcode.PUSH1)}, 0))
return nil, c.SendRawTransaction(transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0))
},
},
{
@ -1066,7 +1066,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{
{
name: "sendrawtransaction_unmarshalling_error",
invoke: func(c *Client) (interface{}, error) {
return nil, c.SendRawTransaction(transaction.New([]byte{byte(opcode.PUSH1)}, 0))
return nil, c.SendRawTransaction(transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0))
},
},
{
@ -1112,7 +1112,7 @@ func testRPCClient(t *testing.T, newClient func(context.Context, string, Options
defer srv.Close()
endpoint := srv.URL
opts := Options{}
opts := Options{Network: netmode.UnitTestNet}
c, err := newClient(context.TODO(), endpoint, opts)
if err != nil {
t.Fatal(err)
@ -1136,7 +1136,7 @@ func testRPCClient(t *testing.T, newClient func(context.Context, string, Options
defer srv.Close()
endpoint := srv.URL
opts := Options{}
opts := Options{Network: netmode.UnitTestNet}
c, err := newClient(context.TODO(), endpoint, opts)
if err != nil {
t.Fatal(err)

View file

@ -137,9 +137,9 @@ readloop:
var val interface{}
switch event {
case response.BlockEventID:
val = new(block.Block)
val = block.New(c.opts.Network)
case response.TransactionEventID:
val = new(transaction.Transaction)
val = &transaction.Transaction{Network: c.opts.Network}
case response.NotificationEventID:
val = new(result.NotificationEvent)
case response.ExecutionEventID:

View file

@ -9,6 +9,7 @@ import (
"time"
"github.com/gorilla/websocket"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/stretchr/testify/require"
@ -17,7 +18,7 @@ import (
func TestWSClientClose(t *testing.T) {
srv := initTestServer(t, "")
defer srv.Close()
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{})
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{Network: netmode.UnitTestNet})
require.NoError(t, err)
wsc.Close()
}
@ -42,7 +43,7 @@ func TestWSClientSubscription(t *testing.T) {
t.Run(name, func(t *testing.T) {
srv := initTestServer(t, `{"jsonrpc": "2.0", "id": 1, "result": "55aaff00"}`)
defer srv.Close()
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{})
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{Network: netmode.UnitTestNet})
require.NoError(t, err)
id, err := f(wsc)
require.NoError(t, err)
@ -55,7 +56,7 @@ func TestWSClientSubscription(t *testing.T) {
t.Run(name, func(t *testing.T) {
srv := initTestServer(t, `{"jsonrpc": "2.0", "id": 1, "error":{"code":-32602,"message":"Invalid Params"}}`)
defer srv.Close()
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{})
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{Network: netmode.UnitTestNet})
require.NoError(t, err)
_, err = f(wsc)
require.Error(t, err)
@ -104,7 +105,7 @@ func TestWSClientUnsubscription(t *testing.T) {
t.Run(name, func(t *testing.T) {
srv := initTestServer(t, rc.response)
defer srv.Close()
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{})
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{Network: netmode.UnitTestNet})
require.NoError(t, err)
rc.code(t, wsc)
})
@ -117,8 +118,8 @@ func TestWSClientEvents(t *testing.T) {
var events = []string{
`{"jsonrpc":"2.0","method":"transaction_executed","params":[{"txid":"0xe1cd5e57e721d2a2e05fb1f08721b12057b25ab1dd7fd0f33ee1639932fdfad7","executions":[{"trigger":"Application","contract":"0x0000000000000000000000000000000000000000","vmstate":"HALT","gas_consumed":"2.291","stack":[],"notifications":[{"contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","state":{"type":"Array","value":[{"type":"ByteArray","value":"Y29udHJhY3QgY2FsbA=="},{"type":"ByteArray","value":"dHJhbnNmZXI="},{"type":"Array","value":[{"type":"ByteArray","value":"dpFiJB7t+XwkgWUq3xug9b9XQxs="},{"type":"ByteArray","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"Integer","value":"1000"}]}]}},{"contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","state":{"type":"Array","value":[{"type":"ByteArray","value":"dHJhbnNmZXI="},{"type":"ByteArray","value":"dpFiJB7t+XwkgWUq3xug9b9XQxs="},{"type":"ByteArray","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"Integer","value":"1000"}]}}]}]}]}`,
`{"jsonrpc":"2.0","method":"notification_from_execution","params":[{"contract":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","state":{"type":"Array","value":[{"type":"ByteArray","value":"Y29udHJhY3QgY2FsbA=="},{"type":"ByteArray","value":"dHJhbnNmZXI="},{"type":"Array","value":[{"type":"ByteArray","value":"dpFiJB7t+XwkgWUq3xug9b9XQxs="},{"type":"ByteArray","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"Integer","value":"1000"}]}]}}]}`,
`{"jsonrpc":"2.0","method":"transaction_added","params":[{"txid":"0x1c615d4043c98fc0e285c2f40cc3601cf4ebe1cf9d2b404dfc67c9cd085444ec","size":265,"version":0,"nonce":9,"sender":"NQRLhCpAru9BjGsMwk67vdMwmzKMRgsnnN","sys_fee":"0","net_fee":"0.0036521","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x870958fd19ee3f6c7dc3c2df399d013910856e31","scopes":"CalledByEntry"}],"script":"AHsMFCBygnSvr8NvQ6Bx0yjPo+Yp2cuwDBQxboUQOQGdOd/Cw31sP+4Z/VgJhxPADAh0cmFuc2ZlcgwUdpFiJB7t+XwkgWUq3xug9b9XQxtBYn1bUjg=","scripts":[{"invocation":"DEA00C87l6Ig/+eWQOSCuIfsDkTcyV5xn14rQ7KZh/DJgiua8EmdkAlMatO6GR5DSj313TeNO3MxjPR8ny1tgBzI","verification":"DCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcILQQqQatQ="}]}]}`,
`{"jsonrpc":"2.0","method":"block_added","params":[{"hash":"0x765ea65b4de6addfee29b1c90ac922d1901c8d7ab7f2366da9a8ad3dd71ca703","version":0,"previousblockhash":"0xbdeed527a43ab72d5d8cecf1dc6ee142112ff8a8eaaaebc7206d3df3bf3c1169","merkleroot":"0xa1b321f59b127cddd23b0cd47fc9ec7920647d30d7ab23318a106597b9c9abad","time":1591366176006,"index":6,"nextconsensus":"Nbb1qkwcwNSBs9pAnrVVrnFbWnbWBk91U2","witnesses":[{"invocation":"DEDaH0tUaopg6WWWNRI013CTkYZrs1kKKQEzvAxFg38drGNR7jJQan4Lv2/LzD7AEiLM/oS8HUBxIh9MQy6/VptiDEDuWQYygBKopKQR5/ojqouiH+24GxFYHloofK2WH6NtKiCyBpVJpaFIYNnprjZA6iD5GR1gq3wq7d9D7dbavlWMDED1OR5559YvfMqpAFEdUw+J3hg/pRvEr3RL2oH3Y+FN3X+5U+abCQFmDUdS8kDVJpNE0LZLULEk0aMWrXJIbaFeDEABL3c/rvKu5K9Z4IO0Q+vmz0BNEvSdMpZsX0jywgPihEKWFaotNMgnNW1Vw74WEvZ6W3Jfb/Sbm5Wx9gMGpytx","verification":"EwwhAhA6f33QFlWFl/eWDSfFFqQ5T9loueZRVetLAT5AQEBuDCECp7xV/oaE4BGXaNEEujB5W9zIZhnoZK3SYVZyPtGFzWIMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwgwhA9kMB99j5pDOd5EuEKtRrMlEtmhgI3tgjE+PgwnnHuaZFAtBMHOzuw=="}],"consensus_data":{"primary":0,"nonce":"0000000000000457"},"tx":[{"txid":"0x1c615d4043c98fc0e285c2f40cc3601cf4ebe1cf9d2b404dfc67c9cd085444ec","size":265,"version":0,"nonce":9,"sender":"NQRLhCpAru9BjGsMwk67vdMwmzKMRgsnnN","sys_fee":"0","net_fee":"0.0036521","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x870958fd19ee3f6c7dc3c2df399d013910856e31","scopes":"CalledByEntry"}],"script":"AHsMFCBygnSvr8NvQ6Bx0yjPo+Yp2cuwDBQxboUQOQGdOd/Cw31sP+4Z/VgJhxPADAh0cmFuc2ZlcgwUdpFiJB7t+XwkgWUq3xug9b9XQxtBYn1bUjg=","scripts":[{"invocation":"DEA00C87l6Ig/+eWQOSCuIfsDkTcyV5xn14rQ7KZh/DJgiua8EmdkAlMatO6GR5DSj313TeNO3MxjPR8ny1tgBzI","verification":"DCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcILQQqQatQ="}]}]}]}`,
`{"jsonrpc":"2.0","method":"transaction_executed","params":[{"txid":"0xf97a72b7722c109f909a8bc16c22368c5023d85828b09b127b237aace33cf099","executions":[{"trigger":"Application","contract":"0x0000000000000000000000000000000000000000","vmstate":"HALT","gas_consumed":"0.0604261","stack":[],"notifications":[{"contract":"0xe65ff7b3a02d207b584a5c27057d4e9862ef01da","state":{"type":"Array","value":[{"type":"ByteArray","value":"Y29udHJhY3QgY2FsbA=="},{"type":"ByteArray","value":"dHJhbnNmZXI="},{"type":"Array","value":[{"type":"ByteArray","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"ByteArray","value":"IHKCdK+vw29DoHHTKM+j5inZy7A="},{"type":"Integer","value":"123"}]}]}},{"contract":"0xe65ff7b3a02d207b584a5c27057d4e9862ef01da","state":{"type":"Array","value":[{"type":"ByteArray","value":"dHJhbnNmZXI="},{"type":"ByteArray","value":"MW6FEDkBnTnfwsN9bD/uGf1YCYc="},{"type":"ByteArray","value":"IHKCdK+vw29DoHHTKM+j5inZy7A="},{"type":"Integer","value":"123"}]}}]}]}]}`,
`{"jsonrpc":"2.0","method":"block_added","params":[{"hash":"0x2d312f6379ead13cf62634c703091b750e7903728df2a3cf5bd96ce80b84a849","version":0,"previousblockhash":"0xb8237d34c156cac6be7b01578decf8ac8c99a62f0b6f774d622aad7be0fe189d","merkleroot":"0xf89169e89361692b71e671f13c088e84c5325015c413e8f89e7ba38efdb41287","time":1592472500006,"index":6,"nextconsensus":"Nbb1qkwcwNSBs9pAnrVVrnFbWnbWBk91U2","witnesses":[{"invocation":"DEDblVguNGXWbUswDvBfVJzBt76BJyJ0Ga6siquyjioGn4Dbr6zy1IvcLl3xN5akcejRy9e+Mr1qvpe/gkLgtW4QDEDRwPISZagMFjE/plXTnZ/gEU0IbBAAe23U29zVWteUmzRsPxF/MdzXvdffR9W0edkj17AmkWpn+5rqzH9aCOpLDECEvjgxZaRoAHEDNzp1REllLcGzMwrwSjudtzfgRglQL3g1BKerDx6cGHH73medRVkL9QVm4KzSxlywVtvhwBMrDEBuPKvzg5TtakFW2jr/bfmy1bn2FiLARlOySwaGdKRV93ozA5lVEIAvHbBlJtT4/5H8jHjbncXXMrP3OUHqebZz","verification":"EwwhAhA6f33QFlWFl/eWDSfFFqQ5T9loueZRVetLAT5AQEBuDCECp7xV/oaE4BGXaNEEujB5W9zIZhnoZK3SYVZyPtGFzWIMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwgwhA9kMB99j5pDOd5EuEKtRrMlEtmhgI3tgjE+PgwnnHuaZFAtBMHOzuw=="}],"consensus_data":{"primary":0,"nonce":"0000000000000457"},"tx":[{"txid":"0xf97a72b7722c109f909a8bc16c22368c5023d85828b09b127b237aace33cf099","size":265,"version":0,"nonce":9,"sender":"NQRLhCpAru9BjGsMwk67vdMwmzKMRgsnnN","sys_fee":"0","net_fee":"0.0036521","valid_until_block":1200,"attributes":[],"cosigners":[{"account":"0x870958fd19ee3f6c7dc3c2df399d013910856e31","scopes":"CalledByEntry"}],"script":"AHsMFCBygnSvr8NvQ6Bx0yjPo+Yp2cuwDBQxboUQOQGdOd/Cw31sP+4Z/VgJhxPADAh0cmFuc2ZlcgwU2gHvYphOfQUnXEpYeyAtoLP3X+ZBYn1bUjg=","scripts":[{"invocation":"DECwklSj3liZOJbktRtkVdUCu8U2LQlrU6Dv8NtMgd0xXbk5lXjc2p68xv6xtJXbJ4aoFMJZ9lkcNpGoeUCcaCet","verification":"DCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcILQQqQatQ="}]}]}]}`,
`{"jsonrpc":"2.0","method":"event_missed","params":[]}`,
}
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
@ -138,7 +139,7 @@ func TestWSClientEvents(t *testing.T) {
}
}))
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{})
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{Network: netmode.UnitTestNet})
require.NoError(t, err)
for range events {
select {
@ -161,7 +162,7 @@ func TestWSExecutionVMStateCheck(t *testing.T) {
// Will answer successfully if request slips through.
srv := initTestServer(t, `{"jsonrpc": "2.0", "id": 1, "result": "55aaff00"}`)
defer srv.Close()
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{})
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{Network: netmode.UnitTestNet})
require.NoError(t, err)
filter := "NONE"
_, err = wsc.SubscribeForTransactionExecutions(&filter)
@ -291,7 +292,7 @@ func TestWSFilteredSubscriptions(t *testing.T) {
}
}))
defer srv.Close()
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{})
wsc, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{Network: netmode.UnitTestNet})
require.NoError(t, err)
c.clientCode(t, wsc)
wsc.Close()
@ -304,11 +305,11 @@ func TestNewWS(t *testing.T) {
defer srv.Close()
t.Run("good", func(t *testing.T) {
_, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{})
_, err := NewWS(context.TODO(), httpURLtoWS(srv.URL), Options{Network: netmode.UnitTestNet})
require.NoError(t, err)
})
t.Run("bad URL", func(t *testing.T) {
_, err := NewWS(context.TODO(), strings.Trim(srv.URL, "http://"), Options{})
_, err := NewWS(context.TODO(), strings.Trim(srv.URL, "http://"), Options{Network: netmode.UnitTestNet})
require.Error(t, err)
})
}

View file

@ -14,7 +14,7 @@ type (
// Block wrapper used for the representation of
// block.Block / block.Base on the RPC Server.
Block struct {
*block.Block
block.Block
BlockMetadata
}
@ -30,7 +30,7 @@ type (
// NewBlock creates a new Block wrapper.
func NewBlock(b *block.Block, chain blockchainer.Blockchainer) Block {
res := Block{
Block: b,
Block: *b,
BlockMetadata: BlockMetadata{
Size: io.GetVarSize(b),
Confirmations: chain.BlockHeight() - b.Index + 1,
@ -72,16 +72,14 @@ func (b *Block) UnmarshalJSON(data []byte) error {
// As block.Block and BlockMetadata are at the same level in json,
// do unmarshalling separately for both structs.
meta := new(BlockMetadata)
base := new(block.Block)
err := json.Unmarshal(data, meta)
if err != nil {
return err
}
err = json.Unmarshal(data, base)
err = json.Unmarshal(data, &b.Block)
if err != nil {
return err
}
b.Block = base
b.BlockMetadata = *meta
return nil
}

View file

@ -13,7 +13,7 @@ import (
// TransactionOutputRaw is used as a wrapper to represents
// a Transaction.
type TransactionOutputRaw struct {
*transaction.Transaction
transaction.Transaction
TransactionMetadata
}
@ -29,7 +29,7 @@ func NewTransactionOutputRaw(tx *transaction.Transaction, header *block.Header,
// confirmations formula
confirmations := int(chain.BlockHeight() - header.Base.Index + 1)
return TransactionOutputRaw{
Transaction: tx,
Transaction: *tx,
TransactionMetadata: TransactionMetadata{
Blockhash: header.Hash(),
Confirmations: confirmations,
@ -48,7 +48,7 @@ func (t TransactionOutputRaw) MarshalJSON() ([]byte, error) {
if err != nil {
return nil, err
}
txBytes, err := json.Marshal(t.Transaction)
txBytes, err := json.Marshal(&t.Transaction)
if err != nil {
return nil, err
}
@ -76,11 +76,5 @@ func (t *TransactionOutputRaw) UnmarshalJSON(data []byte) error {
t.Confirmations = output.Confirmations
t.Timestamp = output.Timestamp
transaction := new(transaction.Transaction)
err = json.Unmarshal(data, transaction)
if err != nil {
return err
}
t.Transaction = transaction
return nil
return json.Unmarshal(data, &t.Transaction)
}

View file

@ -13,6 +13,7 @@ import (
"time"
"github.com/gorilla/websocket"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core"
"github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/blockchainer"
@ -40,6 +41,7 @@ type (
*http.Server
chain blockchainer.Blockchainer
config rpc.Config
network netmode.Magic
coreServer *network.Server
log *zap.Logger
https *http.Server
@ -135,6 +137,7 @@ func New(chain blockchainer.Blockchainer, conf rpc.Config, coreServer *network.S
Server: httpServer,
chain: chain,
config: conf,
network: chain.GetConfig().Magic,
coreServer: coreServer,
log: log,
https: tlsServer,
@ -928,13 +931,13 @@ func (s *Server) submitBlock(reqParams request.Params) (interface{}, *response.E
if err != nil {
return nil, response.ErrInvalidParams
}
b := block.Block{}
b := block.New(s.network)
r := io.NewBinReaderFromBuf(blockBytes)
b.DecodeBinary(r)
if r.Err != nil {
return nil, response.ErrInvalidParams
}
err = s.chain.AddBlock(&b)
err = s.chain.AddBlock(b)
if err != nil {
switch err {
case core.ErrInvalidBlockIndex, core.ErrAlreadyExists:
@ -955,7 +958,7 @@ func (s *Server) sendrawtransaction(reqParams request.Params) (interface{}, *res
} else if byteTx, err := reqParams[0].GetBytesHex(); err != nil {
return nil, response.ErrInvalidParams
} else {
tx, err := transaction.NewTransactionFromBytes(byteTx)
tx, err := transaction.NewTransactionFromBytes(s.network, byteTx)
if err != nil {
return nil, response.ErrInvalidParams
}

View file

@ -7,6 +7,7 @@ import (
"testing"
"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core"
"github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/storage"
@ -19,7 +20,7 @@ import (
)
func getUnitTestChain(t *testing.T) (*core.Blockchain, config.Config, *zap.Logger) {
net := config.ModeUnitTestNet
net := netmode.UnitTestNet
configPath := "../../../config"
cfg, err := config.Load(configPath, net)
require.NoError(t, err, "could not load config")
@ -49,7 +50,7 @@ func getTestBlocks(t *testing.T) []*block.Block {
blocks := make([]*block.Block, 0, int(nBlocks))
for i := 0; i < int(nBlocks); i++ {
_ = br.ReadU32LE()
b := &block.Block{}
b := block.New(netmode.UnitTestNet)
b.DecodeBinary(br)
require.Nil(t, br.Err)
blocks = append(blocks, b)

View file

@ -51,17 +51,18 @@ type rpcTestCase struct {
}
const testContractHash = "e65ff7b3a02d207b584a5c27057d4e9862ef01da"
const deploymentTxHash = "5ce44eae362d3f81d440cb73cf4e4af71e69851bcd683b076aa08b7346d4e69b"
var rpcTestCases = map[string][]rpcTestCase{
"getapplicationlog": {
{
name: "positive",
params: `["9352fa8d351635bb151e7e5a3a923bfe4d8fb90f05b605ec00af95c2410b594d"]`,
params: `["` + deploymentTxHash + `"]`,
result: func(e *executor) interface{} { return &result.ApplicationLog{} },
check: func(t *testing.T, e *executor, acc interface{}) {
res, ok := acc.(*result.ApplicationLog)
require.True(t, ok)
expectedTxHash, err := util.Uint256DecodeStringLE("9352fa8d351635bb151e7e5a3a923bfe4d8fb90f05b605ec00af95c2410b594d")
expectedTxHash, err := util.Uint256DecodeStringLE(deploymentTxHash)
require.NoError(t, err)
assert.Equal(t, expectedTxHash, res.TxHash)
assert.Equal(t, 1, len(res.Executions))
@ -316,7 +317,7 @@ var rpcTestCases = map[string][]rpcTestCase{
{
name: "positive",
params: "[3, 1]",
result: func(e *executor) interface{} { return &result.Block{} },
result: func(_ *executor) interface{} { return &result.Block{} },
check: func(t *testing.T, e *executor, blockRes interface{}) {
res, ok := blockRes.(*result.Block)
require.True(t, ok)
@ -483,7 +484,7 @@ var rpcTestCases = map[string][]rpcTestCase{
"gettransactionheight": {
{
name: "positive",
params: `["9352fa8d351635bb151e7e5a3a923bfe4d8fb90f05b605ec00af95c2410b594d"]`,
params: `["` + deploymentTxHash + `"]`,
result: func(e *executor) interface{} {
h := 0
return &h
@ -687,7 +688,7 @@ var rpcTestCases = map[string][]rpcTestCase{
"sendrawtransaction": {
{
name: "positive",
params: `["000a000000316e851039019d39dfc2c37d6c3fee19fd5809870000000000000000f2ad050000000000b00400000001316e851039019d39dfc2c37d6c3fee19fd580987015d0300e87648170000000c1420728274afafc36f43a071d328cfa3e629d9cbb00c14316e851039019d39dfc2c37d6c3fee19fd58098713c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b523801420c40df953141271169421cebab5d27a0163e294d7c7f2d0525b4498745344814fd3d6c5c591c9b1723d05d42856f409adb084cf67acc921cfafc629133a5eb5e7a7e290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4"]`,
params: `["000a000000316e851039019d39dfc2c37d6c3fee19fd5809870000000000000000f2ad050000000000b00400000001316e851039019d39dfc2c37d6c3fee19fd580987015d0300e87648170000000c1420728274afafc36f43a071d328cfa3e629d9cbb00c14316e851039019d39dfc2c37d6c3fee19fd58098713c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b523801420c409803db41e66a94e0bd6fdd3d7a7b1e106c1e2281c9782a231f32df036bb80c7f19155cdb9a52a45cf8d93ec9c1e8df69d6ee35625f352d1710c7cc6eee26003c290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4"]`,
result: func(e *executor) interface{} {
v := true
return &v
@ -825,7 +826,7 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) []
newTx := func() *transaction.Transaction {
height := chain.BlockHeight()
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx := transaction.New(testchain.Network(), []byte{byte(opcode.PUSH1)}, 0)
tx.Nonce = height + 1
tx.ValidUntilBlock = height + 10
tx.Sender = acc0.PrivateKey().GetScriptHash()
@ -886,11 +887,11 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) []
rpc := fmt.Sprintf(`{"jsonrpc": "2.0", "id": 1, "method": "getrawtransaction", "params": ["%s", 1]}"`, TXHash.StringLE())
body := doRPCCall(rpc, httpSrv.URL, t)
txOut := checkErrGetResult(t, body, false)
actual := result.TransactionOutputRaw{}
actual := result.TransactionOutputRaw{Transaction: transaction.Transaction{Network: testchain.Network()}}
err := json.Unmarshal(txOut, &actual)
require.NoErrorf(t, err, "could not parse response: %s", txOut)
assert.Equal(t, block.Transactions[0], actual.Transaction)
assert.Equal(t, *block.Transactions[0], actual.Transaction)
assert.Equal(t, 8, actual.Confirmations)
assert.Equal(t, TXHash, actual.Transaction.Hash())
})
@ -955,7 +956,7 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) []
expected = append(expected, tx.Hash())
}
for i := 0; i < 5; i++ {
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx := transaction.New(testchain.Network(), []byte{byte(opcode.PUSH1)}, 0)
assert.NoError(t, mp.Add(tx, &FeerStub{}))
expected = append(expected, tx.Hash())
}
@ -1004,6 +1005,7 @@ func newBlock(t *testing.T, bc blockchainer.Blockchainer, index uint32, primary
Index: hdr.Index + index,
NextConsensus: witness.ScriptHash(),
Script: witness,
Network: bc.GetConfig().Magic,
},
ConsensusData: block.ConsensusData{
PrimaryIndex: primary,
@ -1020,7 +1022,12 @@ func newBlock(t *testing.T, bc blockchainer.Blockchainer, index uint32, primary
func (tc rpcTestCase) getResultPair(e *executor) (expected interface{}, res interface{}) {
expected = tc.result(e)
resVal := reflect.New(reflect.TypeOf(expected).Elem())
return expected, resVal.Interface()
res = resVal.Interface()
switch r := res.(type) {
case *result.Block:
r.Network = testchain.Network()
}
return expected, res
}
func checkErrGetResult(t *testing.T, body []byte, expectingFail bool) json.RawMessage {

Binary file not shown.

View file

@ -10,6 +10,7 @@ import (
"strings"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
@ -24,7 +25,7 @@ type ParameterContext struct {
// Type is a type of a verifiable item.
Type string
// Verifiable is an object which can be (de-)serialized.
Verifiable io.Serializable
Verifiable crypto.VerifiableDecodable
// Items is a map from script hashes to context items.
Items map[util.Uint160]*Item
}
@ -41,7 +42,7 @@ type sigWithIndex struct {
}
// NewParameterContext returns ParameterContext with the specified type and item to sign.
func NewParameterContext(typ string, verif io.Serializable) *ParameterContext {
func NewParameterContext(typ string, verif crypto.VerifiableDecodable) *ParameterContext {
return &ParameterContext{
Type: typ,
Verifiable: verif,
@ -144,11 +145,7 @@ func (c *ParameterContext) getItemForContract(ctr *wallet.Contract) *Item {
// MarshalJSON implements json.Marshaler interface.
func (c ParameterContext) MarshalJSON() ([]byte, error) {
bw := io.NewBufBinWriter()
c.Verifiable.EncodeBinary(bw.BinWriter)
if bw.Err != nil {
return nil, bw.Err
}
verif := c.Verifiable.GetSignedPart()
items := make(map[string]json.RawMessage, len(c.Items))
for u := range c.Items {
data, err := json.Marshal(c.Items[u])
@ -159,7 +156,7 @@ func (c ParameterContext) MarshalJSON() ([]byte, error) {
}
pc := &paramContext{
Type: c.Type,
Hex: hex.EncodeToString(bw.Bytes()),
Hex: hex.EncodeToString(verif),
Items: items,
}
return json.Marshal(pc)
@ -176,17 +173,16 @@ func (c *ParameterContext) UnmarshalJSON(data []byte) error {
return err
}
var verif io.Serializable
var verif crypto.VerifiableDecodable
switch pc.Type {
case "Neo.Core.ContractTransaction":
verif = new(transaction.Transaction)
default:
return fmt.Errorf("unsupported type: %s", c.Type)
}
br := io.NewBinReaderFromBuf(data)
verif.DecodeBinary(br)
if br.Err != nil {
return br.Err
err = verif.DecodeSignedPart(data)
if err != nil {
return err
}
items := make(map[util.Uint160]*Item, len(pc.Items))
for h := range pc.Items {

View file

@ -4,6 +4,7 @@ import (
"encoding/hex"
"testing"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/interop"
"github.com/nspcc-dev/neo-go/pkg/core/interop/crypto"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
@ -165,7 +166,7 @@ func newParam(typ smartcontract.ParamType, name string) wallet.ContractParam {
}
func getContractTx() *transaction.Transaction {
tx := transaction.New([]byte{byte(opcode.PUSH1)}, 0)
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx.Attributes = make([]transaction.Attribute, 0)
tx.Scripts = make([]transaction.Witness, 0)
tx.Hash()