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

View file

@ -2,7 +2,6 @@ package smartcontract
import ( import (
"bytes" "bytes"
"context"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
@ -14,11 +13,11 @@ import (
"github.com/go-yaml/yaml" "github.com/go-yaml/yaml"
"github.com/nspcc-dev/neo-go/cli/flags" "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/compiler"
"github.com/nspcc-dev/neo-go/pkg/core/transaction" "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/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "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/request"
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result" "github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
"github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract"
@ -32,7 +31,6 @@ import (
) )
var ( 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") 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") 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") 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") 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") 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{ walletFlag = cli.StringFlag{
Name: "wallet, w", Name: "wallet, w",
Usage: "wallet to use to get the key for transaction signing", 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. // NewCommands returns 'contract' command.
func NewCommands() []cli.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{{ return []cli.Command{{
Name: "contract", Name: "contract",
Usage: "compile - debug - deploy smart contracts", Usage: "compile - debug - deploy smart contracts",
@ -121,42 +142,24 @@ func NewCommands() []cli.Command {
to it). to it).
`, `,
Action: contractDeploy, Action: contractDeploy,
Flags: []cli.Flag{ Flags: deployFlags,
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,
},
}, },
{ {
Name: "invokefunction", Name: "invokefunction",
Usage: "invoke deployed contract on the blockchain", 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, Description: `Executes given (as a script hash) deployed script with the given method,
arguments and cosigners. See testinvokefunction documentation for the details arguments and cosigners. See testinvokefunction documentation for the details
about parameters. It differs from testinvokefunction in that this command about parameters. It differs from testinvokefunction in that this command
sends an invocation transaction to the network. sends an invocation transaction to the network.
`, `,
Action: invokeFunction, Action: invokeFunction,
Flags: []cli.Flag{ Flags: invokeFunctionFlags,
endpointFlag,
walletFlag,
addressFlag,
gasFlag,
},
}, },
{ {
Name: "testinvokefunction", Name: "testinvokefunction",
Usage: "invoke deployed contract on the blockchain (test mode)", 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, 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 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, 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' * '0000000009070e030d0f0e020d0c06050e030c02:CalledByEntry,CustomGroups'
`, `,
Action: testInvokeFunction, Action: testInvokeFunction,
Flags: []cli.Flag{ Flags: options.RPC,
endpointFlag,
},
}, },
{ {
Name: "testinvokescript", Name: "testinvokescript",
Usage: "Invoke compiled AVM code on the blockchain (test mode, not creating a transaction for it)", 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 Description: `Executes given compiled AVM instructions with the given set of
cosigners. See testinvokefunction documentation for the details about parameters. cosigners. See testinvokefunction documentation for the details about parameters.
`, `,
Action: testInvokeScript, Action: testInvokeScript,
Flags: []cli.Flag{ Flags: testInvokeScriptFlags,
endpointFlag,
cli.StringFlag{
Name: "in, i",
Usage: "Input location of the avm file that needs to be invoked",
},
},
}, },
{ {
Name: "init", Name: "init",
@ -407,11 +402,6 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error {
acc *wallet.Account acc *wallet.Account
) )
endpoint := ctx.String("endpoint")
if len(endpoint) == 0 {
return cli.NewExitError(errNoEndpoint, 1)
}
args := ctx.Args() args := ctx.Args()
if !args.Present() { if !args.Present() {
return cli.NewExitError(errNoScriptHash, 1) return cli.NewExitError(errNoScriptHash, 1)
@ -455,9 +445,12 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error {
return err 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 { if err != nil {
return cli.NewExitError(err, 1) return err
} }
resp, err = c.InvokeFunction(script, operation, params, cosigners) resp, err = c.InvokeFunction(script, operation, params, cosigners)
@ -494,10 +487,6 @@ func testInvokeScript(ctx *cli.Context) error {
if len(src) == 0 { if len(src) == 0 {
return cli.NewExitError(errNoInput, 1) return cli.NewExitError(errNoInput, 1)
} }
endpoint := ctx.String("endpoint")
if len(endpoint) == 0 {
return cli.NewExitError(errNoEndpoint, 1)
}
b, err := ioutil.ReadFile(src) b, err := ioutil.ReadFile(src)
if err != nil { 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 { if err != nil {
return cli.NewExitError(err, 1) return err
} }
scriptHex := hex.EncodeToString(b) scriptHex := hex.EncodeToString(b)
@ -640,10 +632,6 @@ func contractDeploy(ctx *cli.Context) error {
if len(confFile) == 0 { if len(confFile) == 0 {
return cli.NewExitError(errNoConfFile, 1) return cli.NewExitError(errNoConfFile, 1)
} }
endpoint := ctx.String("endpoint")
if len(endpoint) == 0 {
return cli.NewExitError(errNoEndpoint, 1)
}
gas := flags.Fixed8FromContext(ctx, "gas") gas := flags.Fixed8FromContext(ctx, "gas")
acc, err := getAccFromContext(ctx) acc, err := getAccFromContext(ctx)
@ -659,9 +647,12 @@ func contractDeploy(ctx *cli.Context) error {
return err 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 { if err != nil {
return cli.NewExitError(err, 1) return err
} }
m := conf.ToManifest(avm) m := conf.ToManifest(avm)

View file

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

View file

@ -7,6 +7,7 @@ import (
"io/ioutil" "io/ioutil"
"github.com/nspcc-dev/neo-go/cli/flags" "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/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/rpc/client" "github.com/nspcc-dev/neo-go/pkg/rpc/client"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/context" "github.com/nspcc-dev/neo-go/pkg/smartcontract/context"
@ -16,16 +17,8 @@ import (
) )
func newNEP5Commands() []cli.Command { func newNEP5Commands() []cli.Command {
return []cli.Command{ balanceFlags := []cli.Flag{
{
Name: "balance",
Usage: "get address balance",
UsageText: "balance --path <path> --rpc <node> --addr <addr> [--token <hash-or-name>]",
Action: getNEP5Balance,
Flags: []cli.Flag{
walletPathFlag, walletPathFlag,
rpcFlag,
timeoutFlag,
cli.StringFlag{ cli.StringFlag{
Name: "addr", Name: "addr",
Usage: "Address to use", Usage: "Address to use",
@ -34,21 +27,49 @@ func newNEP5Commands() []cli.Command {
Name: "token", Name: "token",
Usage: "Token to use", Usage: "Token to use",
}, },
}, }
}, balanceFlags = append(balanceFlags, options.RPC...)
{ importFlags := []cli.Flag{
Name: "import",
Usage: "import NEP5 token to a wallet",
UsageText: "import --path <path> --rpc <node> --token <hash>",
Action: importNEP5Token,
Flags: []cli.Flag{
walletPathFlag, walletPathFlag,
rpcFlag,
cli.StringFlag{ cli.StringFlag{
Name: "token", Name: "token",
Usage: "Token contract hash in LE", 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-endpoint <node> --timeout <time> --addr <addr> [--token <hash-or-name>]",
Action: getNEP5Balance,
Flags: balanceFlags,
},
{
Name: "import",
Usage: "import NEP5 token to a wallet",
UsageText: "import --path <path> --rpc-endpoint <node> --timeout <time> --token <hash>",
Action: importNEP5Token,
Flags: importFlags,
}, },
{ {
Name: "info", Name: "info",
@ -80,28 +101,9 @@ func newNEP5Commands() []cli.Command {
{ {
Name: "transfer", Name: "transfer",
Usage: "transfer NEP5 tokens", 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, Action: transferNEP5,
Flags: []cli.Flag{ Flags: transferFlags,
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",
},
},
}, },
} }
} }
@ -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) 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() defer cancel()
c, err := client.New(gctx, ctx.String("rpc"), client.Options{}) c, err := options.GetRPCClient(gctx, ctx)
if err != nil { if err != nil {
return cli.NewExitError(err, 1) return err
} }
var token *wallet.Token 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() defer cancel()
c, err := client.New(gctx, ctx.String("rpc"), client.Options{}) c, err := options.GetRPCClient(gctx, ctx)
if err != nil { if err != nil {
return cli.NewExitError(err, 1) return err
} }
tok, err := c.NEP5TokenInfo(tokenHash) 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) 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() defer cancel()
c, err := client.New(gctx, ctx.String("rpc"), client.Options{})
c, err := options.GetRPCClient(gctx, ctx)
if err != nil { if err != nil {
return cli.NewExitError(err, 1) return err
} }
toFlag := ctx.Generic("to").(*flags.Address) toFlag := ctx.Generic("to").(*flags.Address)

View file

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

View file

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

View file

@ -144,10 +144,10 @@ project:
It's passed to the `deploy` command via `-c` option: 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 option and should be signed using a wallet from `-w` option. More details can
be found in `deploy` command help. 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): 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 ## Smart contract examples

View file

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

View file

@ -7,6 +7,7 @@ import (
"testing" "testing"
"github.com/nspcc-dev/neo-go/pkg/compiler" "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"
"github.com/nspcc-dev/neo-go/pkg/core/dao" "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/interop"
@ -80,7 +81,7 @@ func TestAppCall(t *testing.T) {
inner, err := compiler.Compile(strings.NewReader(srcInner)) inner, err := compiler.Compile(strings.NewReader(srcInner))
require.NoError(t, err) 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})) require.NoError(t, ic.DAO.PutContractState(&state.Contract{Script: inner}))
ih := hash.Hash160(inner) ih := hash.Hash160(inner)

View file

@ -6,6 +6,7 @@ import (
"os" "os"
"github.com/go-yaml/yaml" "github.com/go-yaml/yaml"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -28,7 +29,7 @@ func (c Config) GenerateUserAgent() string {
// Load attempts to load the config from the given // Load attempts to load the config from the given
// path for the given netMode. // 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) configPath := fmt.Sprintf("%s/protocol.%s.yml", path, netMode)
if _, err := os.Stat(configPath); os.IsNotExist(err) { if _, err := os.Stat(configPath); os.IsNotExist(err) {
return Config{}, errors.Wrap(err, "Unable to load config") 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 package config
import ( import (
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/util" "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. // ProtocolConfiguration represents the protocol config.
type ( type (
ProtocolConfiguration struct { ProtocolConfiguration struct {
@ -24,7 +14,7 @@ type (
// FreeGasLimit is an amount of GAS which can be spent for free. // FreeGasLimit is an amount of GAS which can be spent for free.
FreeGasLimit util.Fixed8 `yaml:"FreeGasLimit"` FreeGasLimit util.Fixed8 `yaml:"FreeGasLimit"`
LowPriorityThreshold float64 `yaml:"LowPriorityThreshold"` LowPriorityThreshold float64 `yaml:"LowPriorityThreshold"`
Magic NetMode `yaml:"Magic"` Magic netmode.Magic `yaml:"Magic"`
MaxTransactionsPerBlock int `yaml:"MaxTransactionsPerBlock"` MaxTransactionsPerBlock int `yaml:"MaxTransactionsPerBlock"`
// Maximum size of low priority transaction in bytes. // Maximum size of low priority transaction in bytes.
MaxFreeTransactionSize int `yaml:"MaxFreeTransactionSize"` MaxFreeTransactionSize int `yaml:"MaxFreeTransactionSize"`
@ -41,23 +31,4 @@ type (
// Whether to verify transactions in received blocks. // Whether to verify transactions in received blocks.
VerifyTransactions bool `yaml:"VerifyTransactions"` 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/block"
"github.com/nspcc-dev/dbft/crypto" "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/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode" "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} b.Block.PrevHash = util.Uint256{9, 8, 7}
require.Equal(t, util.Uint256{9, 8, 7}, b.PrevHash()) 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) b.SetTransactions(txx)
require.Equal(t, txx, b.Transactions()) require.Equal(t, txx, b.Transactions())
} }

View file

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

View file

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

View file

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

View file

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

View file

@ -3,6 +3,7 @@ package block
import ( import (
"testing" "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/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/nspcc-dev/neo-go/pkg/vm/opcode"
@ -85,7 +86,7 @@ func newDumbBlock() *Block {
Nonce: 1111, Nonce: 1111,
}, },
Transactions: []*transaction.Transaction{ 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() b := buf.Bytes()
c.hash = hash.Sha256(b) c.hash = hash.DoubleSha256(b)
return nil return nil
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -5,6 +5,7 @@ import (
"runtime" "runtime"
"testing" "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/dao"
"github.com/nspcc-dev/neo-go/pkg/core/interop" "github.com/nspcc-dev/neo-go/pkg/core/interop"
"github.com/nspcc-dev/neo-go/pkg/core/storage" "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) v.Estack().PushVal(value)
chain := newTestChain(t) chain := newTestChain(t)
defer chain.Close() 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)) require.Error(t, f(context, v))
} }

View file

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

View file

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

View file

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

View file

@ -5,6 +5,7 @@ import (
"errors" "errors"
"math/rand" "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/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
@ -58,6 +59,11 @@ type Transaction struct {
// and invocation script. // and invocation script.
Scripts []Witness 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 of the transaction (double SHA256).
hash util.Uint256 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 // New returns a new transaction to execute given script and pay given system
// fee. // fee.
func New(script []byte, gas util.Fixed8) *Transaction { func New(network netmode.Magic, script []byte, gas util.Fixed8) *Transaction {
return &Transaction{ return &Transaction{
Version: 0, Version: 0,
Nonce: rand.Uint32(), Nonce: rand.Uint32(),
@ -89,6 +95,7 @@ func New(script []byte, gas util.Fixed8) *Transaction {
Attributes: []Attribute{}, Attributes: []Attribute{},
Cosigners: []Cosigner{}, Cosigners: []Cosigner{},
Scripts: []Witness{}, Scripts: []Witness{},
Network: network,
} }
} }
@ -112,8 +119,9 @@ func (t *Transaction) VerificationHash() util.Uint256 {
return t.verificationHash return t.verificationHash
} }
// DecodeBinary implements Serializable interface. // decodeHashableFields decodes the fields that are used for signing the
func (t *Transaction) DecodeBinary(br *io.BinReader) { // transaction, which are all fields except the scripts.
func (t *Transaction) decodeHashableFields(br *io.BinReader) {
t.Version = uint8(br.ReadB()) t.Version = uint8(br.ReadB())
if t.Version > 0 { if t.Version > 0 {
br.Err = errors.New("only version 0 is supported") 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") br.Err = errors.New("no script")
return return
} }
}
// DecodeBinary implements Serializable interface.
func (t *Transaction) DecodeBinary(br *io.BinReader) {
t.decodeHashableFields(br)
if br.Err != nil {
return
}
br.ReadArray(&t.Scripts) br.ReadArray(&t.Scripts)
// Create the hash of the transaction at decode, so we dont need // 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. // createHash creates the hash of the transaction.
func (t *Transaction) createHash() error { func (t *Transaction) createHash() error {
buf := io.NewBufBinWriter() b := t.GetSignedPart()
t.encodeHashableFields(buf.BinWriter) if b == nil {
if buf.Err != nil { return errors.New("failed to serialize hashable data")
return buf.Err }
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.verificationHash = hash.Sha256(b)
t.hash = hash.Sha256(t.verificationHash.BytesBE()) t.hash = hash.Sha256(t.verificationHash.BytesBE())
return nil
} }
// GetSignedPart returns a part of the transaction which must be signed. // GetSignedPart returns a part of the transaction which must be signed.
func (t *Transaction) GetSignedPart() []byte { func (t *Transaction) GetSignedPart() []byte {
buf := io.NewBufBinWriter() buf := io.NewBufBinWriter()
buf.WriteU32LE(uint32(t.Network))
t.encodeHashableFields(buf.BinWriter) t.encodeHashableFields(buf.BinWriter)
if buf.Err != nil { if buf.Err != nil {
return nil return nil
@ -218,6 +236,24 @@ func (t *Transaction) GetSignedPart() []byte {
return buf.Bytes() 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 // Bytes converts the transaction to []byte
func (t *Transaction) Bytes() []byte { func (t *Transaction) Bytes() []byte {
buf := io.NewBufBinWriter() buf := io.NewBufBinWriter()
@ -229,8 +265,8 @@ func (t *Transaction) Bytes() []byte {
} }
// NewTransactionFromBytes decodes byte array into *Transaction // NewTransactionFromBytes decodes byte array into *Transaction
func NewTransactionFromBytes(b []byte) (*Transaction, error) { func NewTransactionFromBytes(network netmode.Magic, b []byte) (*Transaction, error) {
tx := &Transaction{} tx := &Transaction{Network: network}
r := io.NewBinReaderFromBuf(b) r := io.NewBinReaderFromBuf(b)
tx.DecodeBinary(r) tx.DecodeBinary(r)
if r.Err != nil { if r.Err != nil {

View file

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

View file

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

View file

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

View file

@ -4,3 +4,10 @@ package crypto
type Verifiable interface { type Verifiable interface {
GetSignedPart() []byte 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 package network
import ( import (
"bytes"
"io"
"github.com/pierrec/lz4" "github.com/pierrec/lz4"
) )
// compress compresses bytes using lz4. // compress compresses bytes using lz4.
func compress(source []byte) ([]byte, error) { func compress(source []byte) ([]byte, error) {
dest := new(bytes.Buffer) dest := make([]byte, lz4.CompressBlockBound(len(source)))
w := lz4.NewWriter(dest) size, err := lz4.CompressBlock(source, dest, nil)
_, err := io.Copy(w, bytes.NewReader(source))
if err != nil { if err != nil {
return nil, err return nil, err
} }
if w.Close() != nil { return dest[:size], nil
return nil, err
}
return dest.Bytes(), nil
} }
// decompress decompresses bytes using lz4. // decompress decompresses bytes using lz4.
func decompress(source []byte) ([]byte, error) { func decompress(source []byte) ([]byte, error) {
dest := new(bytes.Buffer) maxSize := len(source) * 255
r := lz4.NewReader(bytes.NewReader(source)) if maxSize > PayloadMaxSize {
_, err := io.Copy(dest, r) maxSize = PayloadMaxSize
}
dest := make([]byte, maxSize)
size, err := lz4.UncompressBlock(source, dest)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return dest.Bytes(), nil return dest[:size], nil
} }

View file

@ -4,6 +4,7 @@ import (
"errors" "errors"
"fmt" "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/consensus"
"github.com/nspcc-dev/neo-go/pkg/core/block" "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/core/transaction"
@ -33,6 +34,10 @@ type Message struct {
// Compressed message payload. // Compressed message payload.
compressedPayload []byte 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 // MessageFlag represents compression level of message payload
@ -40,8 +45,8 @@ type MessageFlag byte
// Possible message flags // Possible message flags
const ( const (
None MessageFlag = 0
Compressed MessageFlag = 1 << iota Compressed MessageFlag = 1 << iota
None MessageFlag = 0
) )
// CommandType represents the type of a message command. // CommandType represents the type of a message command.
@ -83,7 +88,8 @@ const (
CMDAlert CommandType = 0x40 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 { func NewMessage(cmd CommandType, p payload.Payload) *Message {
return &Message{ return &Message{
Command: cmd, Command: cmd,
@ -103,14 +109,14 @@ func (m *Message) Decode(br *io.BinReader) error {
m.Payload = payload.NewNullPayload() m.Payload = payload.NewNullPayload()
return nil return nil
} }
if l > PayloadMaxSize {
return errors.New("invalid payload size")
}
m.compressedPayload = make([]byte, l) m.compressedPayload = make([]byte, l)
br.ReadBytes(m.compressedPayload) br.ReadBytes(m.compressedPayload)
if br.Err != nil { if br.Err != nil {
return br.Err return br.Err
} }
if len(m.compressedPayload) > PayloadMaxSize {
return errors.New("invalid payload size")
}
return m.decodePayload() return m.decodePayload()
} }
@ -135,7 +141,7 @@ func (m *Message) decodePayload() error {
case CMDAddr: case CMDAddr:
p = &payload.AddressList{} p = &payload.AddressList{}
case CMDBlock: case CMDBlock:
p = &block.Block{} p = block.New(m.Network)
case CMDConsensus: case CMDConsensus:
p = &consensus.Payload{} p = &consensus.Payload{}
case CMDGetBlocks: case CMDGetBlocks:
@ -145,9 +151,9 @@ func (m *Message) decodePayload() error {
case CMDGetBlockData: case CMDGetBlockData:
p = &payload.GetBlockData{} p = &payload.GetBlockData{}
case CMDHeaders: case CMDHeaders:
p = &payload.Headers{} p = &payload.Headers{Network: m.Network}
case CMDTX: case CMDTX:
p = &transaction.Transaction{} p = &transaction.Transaction{Network: m.Network}
case CMDMerkleBlock: case CMDMerkleBlock:
p = &payload.MerkleBlock{} p = &payload.MerkleBlock{}
case CMDPing, CMDPong: case CMDPing, CMDPong:

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -5,13 +5,14 @@ import (
"fmt" "fmt"
"os" "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/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/rpc/client" "github.com/nspcc-dev/neo-go/pkg/rpc/client"
) )
func Example() { func Example() {
endpoint := "http://seed5.bridgeprotocol.io:10332" endpoint := "http://seed5.bridgeprotocol.io:10332"
opts := client.Options{} opts := client.Options{Network: netmode.MainNet}
c, err := client.New(context.TODO(), endpoint, opts) c, err := client.New(context.TODO(), endpoint, opts)
if err != nil { 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) emit.Opcode(w.BinWriter, opcode.ASSERT)
script := w.Bytes() script := w.Bytes()
tx := transaction.New(script, gas) tx := transaction.New(c.opts.Network, script, gas)
tx.Sender = from tx.Sender = from
tx.Cosigners = []transaction.Cosigner{ tx.Cosigners = []transaction.Cosigner{
{ {

View file

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

View file

@ -11,6 +11,7 @@ import (
"time" "time"
"github.com/gorilla/websocket" "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/block"
"github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/core/transaction"
@ -35,17 +36,17 @@ type rpcClientTestCase struct {
check func(t *testing.T, c *Client, result interface{}) 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. // getResultBlock1 returns data for block number 1 which is used by several tests.
func getResultBlock1() *result.Block { func getResultBlock1() *result.Block {
@ -53,17 +54,17 @@ func getResultBlock1() *result.Block {
if err != nil { if err != nil {
panic(err) panic(err)
} }
b := new(block.Block) b := block.New(netmode.UnitTestNet)
err = testserdes.DecodeBinary(binB, b) err = testserdes.DecodeBinary(binB, b)
if err != nil { if err != nil {
panic(err) panic(err)
} }
b2Hash, err := util.Uint256DecodeStringLE("f2afe371a27c9dbac4f4a8ad8eba750898b7c04aa298e64fe9e488e947976045") b2Hash, err := util.Uint256DecodeStringLE("45f62d72e37b074ecdc9f687222b0f91ec98d6d9af4429a2caa2e076a9196b0d")
if err != nil { if err != nil {
panic(err) panic(err)
} }
return &result.Block{ return &result.Block{
Block: b, Block: *b,
BlockMetadata: result.BlockMetadata{ BlockMetadata: result.BlockMetadata{
Size: 1681, Size: 1681,
NextBlockHash: &b2Hash, NextBlockHash: &b2Hash,
@ -78,13 +79,12 @@ func getTxMoveNeo() *result.TransactionOutputRaw {
if err != nil { if err != nil {
panic(err) panic(err)
} }
tx := new(transaction.Transaction) tx, err := transaction.NewTransactionFromBytes(netmode.UnitTestNet, txBin)
err = testserdes.DecodeBinary(txBin, tx)
if err != nil { if err != nil {
panic(err) panic(err)
} }
return &result.TransactionOutputRaw{ return &result.TransactionOutputRaw{
Transaction: tx, Transaction: *tx,
TransactionMetadata: result.TransactionMetadata{ TransactionMetadata: result.TransactionMetadata{
Timestamp: b1.Timestamp, Timestamp: b1.Timestamp,
Blockhash: b1.Block.Hash(), Blockhash: b1.Block.Hash(),
@ -154,7 +154,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
serverResponse: `{"id":1,"jsonrpc":"2.0","result":"` + hexB1 + `"}`, serverResponse: `{"id":1,"jsonrpc":"2.0","result":"` + hexB1 + `"}`,
result: func(c *Client) interface{} { result: func(c *Client) interface{} {
b := getResultBlock1() 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 + `"}`, serverResponse: `{"id":1,"jsonrpc":"2.0","result":"` + hexB1 + `"}`,
result: func(c *Client) interface{} { result: func(c *Client) interface{} {
b := getResultBlock1() 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 + `"}`, serverResponse: `{"id":1,"jsonrpc":"2.0","result":"` + hexTxMoveNeo + `"}`,
result: func(c *Client) interface{} { result: func(c *Client) interface{} {
tx := getTxMoveNeo() tx := getTxMoveNeo()
return tx.Transaction return &tx.Transaction
}, },
}, },
{ {
@ -619,7 +619,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
{ {
name: "positive", name: "positive",
invoke: func(c *Client) (interface{}, 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))
}, },
serverResponse: `{"jsonrpc":"2.0","id":1,"result":true}`, serverResponse: `{"jsonrpc":"2.0","id":1,"result":true}`,
result: func(c *Client) interface{} { result: func(c *Client) interface{} {
@ -740,7 +740,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{
{ {
name: "sendrawtransaction_bad_server_answer", name: "sendrawtransaction_bad_server_answer",
invoke: func(c *Client) (interface{}, 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))
}, },
}, },
{ {
@ -1066,7 +1066,7 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{
{ {
name: "sendrawtransaction_unmarshalling_error", name: "sendrawtransaction_unmarshalling_error",
invoke: func(c *Client) (interface{}, 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() defer srv.Close()
endpoint := srv.URL endpoint := srv.URL
opts := Options{} opts := Options{Network: netmode.UnitTestNet}
c, err := newClient(context.TODO(), endpoint, opts) c, err := newClient(context.TODO(), endpoint, opts)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -1136,7 +1136,7 @@ func testRPCClient(t *testing.T, newClient func(context.Context, string, Options
defer srv.Close() defer srv.Close()
endpoint := srv.URL endpoint := srv.URL
opts := Options{} opts := Options{Network: netmode.UnitTestNet}
c, err := newClient(context.TODO(), endpoint, opts) c, err := newClient(context.TODO(), endpoint, opts)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

View file

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

View file

@ -9,6 +9,7 @@ import (
"time" "time"
"github.com/gorilla/websocket" "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/rpc/request"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -17,7 +18,7 @@ import (
func TestWSClientClose(t *testing.T) { func TestWSClientClose(t *testing.T) {
srv := initTestServer(t, "") srv := initTestServer(t, "")
defer srv.Close() 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) require.NoError(t, err)
wsc.Close() wsc.Close()
} }
@ -42,7 +43,7 @@ func TestWSClientSubscription(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
srv := initTestServer(t, `{"jsonrpc": "2.0", "id": 1, "result": "55aaff00"}`) srv := initTestServer(t, `{"jsonrpc": "2.0", "id": 1, "result": "55aaff00"}`)
defer srv.Close() 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) require.NoError(t, err)
id, err := f(wsc) id, err := f(wsc)
require.NoError(t, err) require.NoError(t, err)
@ -55,7 +56,7 @@ func TestWSClientSubscription(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
srv := initTestServer(t, `{"jsonrpc": "2.0", "id": 1, "error":{"code":-32602,"message":"Invalid Params"}}`) srv := initTestServer(t, `{"jsonrpc": "2.0", "id": 1, "error":{"code":-32602,"message":"Invalid Params"}}`)
defer srv.Close() 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) require.NoError(t, err)
_, err = f(wsc) _, err = f(wsc)
require.Error(t, err) require.Error(t, err)
@ -104,7 +105,7 @@ func TestWSClientUnsubscription(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
srv := initTestServer(t, rc.response) srv := initTestServer(t, rc.response)
defer srv.Close() 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) require.NoError(t, err)
rc.code(t, wsc) rc.code(t, wsc)
}) })
@ -117,8 +118,8 @@ func TestWSClientEvents(t *testing.T) {
var events = []string{ 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":"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":"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":"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":"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":"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":[]}`, `{"jsonrpc":"2.0","method":"event_missed","params":[]}`,
} }
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 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) require.NoError(t, err)
for range events { for range events {
select { select {
@ -161,7 +162,7 @@ func TestWSExecutionVMStateCheck(t *testing.T) {
// Will answer successfully if request slips through. // Will answer successfully if request slips through.
srv := initTestServer(t, `{"jsonrpc": "2.0", "id": 1, "result": "55aaff00"}`) srv := initTestServer(t, `{"jsonrpc": "2.0", "id": 1, "result": "55aaff00"}`)
defer srv.Close() 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) require.NoError(t, err)
filter := "NONE" filter := "NONE"
_, err = wsc.SubscribeForTransactionExecutions(&filter) _, err = wsc.SubscribeForTransactionExecutions(&filter)
@ -291,7 +292,7 @@ func TestWSFilteredSubscriptions(t *testing.T) {
} }
})) }))
defer srv.Close() 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) require.NoError(t, err)
c.clientCode(t, wsc) c.clientCode(t, wsc)
wsc.Close() wsc.Close()
@ -304,11 +305,11 @@ func TestNewWS(t *testing.T) {
defer srv.Close() defer srv.Close()
t.Run("good", func(t *testing.T) { 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) require.NoError(t, err)
}) })
t.Run("bad URL", func(t *testing.T) { 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) require.Error(t, err)
}) })
} }

View file

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

View file

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

View file

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

View file

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

View file

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

Binary file not shown.

View file

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

View file

@ -4,6 +4,7 @@ import (
"encoding/hex" "encoding/hex"
"testing" "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"
"github.com/nspcc-dev/neo-go/pkg/core/interop/crypto" "github.com/nspcc-dev/neo-go/pkg/core/interop/crypto"
"github.com/nspcc-dev/neo-go/pkg/core/transaction" "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 { 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.Attributes = make([]transaction.Attribute, 0)
tx.Scripts = make([]transaction.Witness, 0) tx.Scripts = make([]transaction.Witness, 0)
tx.Hash() tx.Hash()