2022-07-21 13:21:44 +00:00
package rpcsrv
2019-01-22 12:14:52 +00:00
import (
"bytes"
2020-11-06 14:37:58 +00:00
"encoding/base64"
2019-09-18 15:21:16 +00:00
"encoding/json"
2019-01-22 12:14:52 +00:00
"fmt"
2022-02-22 16:27:32 +00:00
gio "io"
2022-06-15 18:23:29 +00:00
"math"
2020-07-09 09:57:24 +00:00
"math/big"
2019-01-22 12:14:52 +00:00
"net/http"
"net/http/httptest"
2019-11-21 16:41:28 +00:00
"reflect"
2020-09-21 12:34:04 +00:00
"sort"
2020-08-07 06:42:44 +00:00
"strconv"
2019-02-09 15:53:58 +00:00
"strings"
2019-01-22 12:14:52 +00:00
"testing"
2020-04-23 13:32:53 +00:00
"time"
2019-01-22 12:14:52 +00:00
2022-06-15 18:23:29 +00:00
"github.com/google/uuid"
2020-04-29 12:25:58 +00:00
"github.com/gorilla/websocket"
2020-11-23 11:09:00 +00:00
"github.com/nspcc-dev/neo-go/internal/testchain"
"github.com/nspcc-dev/neo-go/internal/testserdes"
2022-04-26 09:32:06 +00:00
"github.com/nspcc-dev/neo-go/pkg/config"
2020-03-03 14:21:42 +00:00
"github.com/nspcc-dev/neo-go/pkg/core"
2020-04-23 13:02:01 +00:00
"github.com/nspcc-dev/neo-go/pkg/core/block"
2020-09-28 14:56:16 +00:00
"github.com/nspcc-dev/neo-go/pkg/core/fee"
2021-11-20 18:55:55 +00:00
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
2020-06-09 09:12:56 +00:00
"github.com/nspcc-dev/neo-go/pkg/core/state"
2022-07-08 18:17:52 +00:00
"github.com/nspcc-dev/neo-go/pkg/core/storage/dboper"
2020-03-03 14:21:42 +00:00
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
2021-11-20 18:55:55 +00:00
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
2020-09-28 11:58:04 +00:00
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
2020-03-05 12:16:03 +00:00
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
2020-03-04 17:35:37 +00:00
"github.com/nspcc-dev/neo-go/pkg/io"
2022-07-22 16:09:29 +00:00
"github.com/nspcc-dev/neo-go/pkg/neorpc"
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
2021-10-20 11:32:01 +00:00
"github.com/nspcc-dev/neo-go/pkg/network"
2021-02-09 09:05:45 +00:00
"github.com/nspcc-dev/neo-go/pkg/network/payload"
2021-02-03 19:01:20 +00:00
rpc2 "github.com/nspcc-dev/neo-go/pkg/services/oracle/broadcaster"
2022-07-22 16:09:29 +00:00
"github.com/nspcc-dev/neo-go/pkg/services/rpcsrv/params"
2022-08-22 15:50:35 +00:00
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
2020-09-03 16:58:50 +00:00
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
2020-03-03 14:21:42 +00:00
"github.com/nspcc-dev/neo-go/pkg/util"
2021-03-10 14:43:52 +00:00
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
2022-07-08 17:49:21 +00:00
"github.com/nspcc-dev/neo-go/pkg/vm/invocations"
2020-06-05 09:17:16 +00:00
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
2021-11-20 18:55:55 +00:00
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
2022-07-08 14:28:29 +00:00
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
2020-04-23 13:32:53 +00:00
"github.com/nspcc-dev/neo-go/pkg/wallet"
2019-01-22 12:14:52 +00:00
"github.com/stretchr/testify/assert"
2019-11-21 16:41:28 +00:00
"github.com/stretchr/testify/require"
2021-10-20 11:32:01 +00:00
"go.uber.org/zap/zapcore"
2019-01-22 12:14:52 +00:00
)
2019-11-21 16:41:28 +00:00
type executor struct {
chain * core . Blockchain
2020-04-29 12:14:56 +00:00
httpSrv * httptest . Server
2019-11-21 16:41:28 +00:00
}
2019-02-20 17:39:32 +00:00
2019-11-21 16:41:28 +00:00
type rpcTestCase struct {
name string
params string
fail bool
result func ( e * executor ) interface { }
check func ( t * testing . T , e * executor , result interface { } )
}
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
2022-06-15 18:23:29 +00:00
const genesisBlockHash = "0f8fb4e17d2ab9f3097af75ca7fd16064160fb8043db94909e00dd4e257b9dc4"
2022-03-11 10:22:36 +00:00
const testContractHash = "2db7d679c538ace5f00495c9e9d8ea95f1e0f5a5"
const deploymentTxHash = "496bccb5cb0a008ef9b7a32c459e508ef24fbb0830f82bac9162afa4ca804839"
2022-02-04 16:21:12 +00:00
const (
2022-03-11 10:22:36 +00:00
verifyContractHash = "06ed5314c2e4cb103029a60b86d46afa2fb8f67c"
2022-02-04 16:21:12 +00:00
verifyContractAVM = "VwIAQS1RCDBwDBTunqIsJ+NL0BSPxBCOCPdOj1BIskrZMCQE2zBxaBPOStkoJATbKGlK2SgkBNsol0A="
2022-03-11 10:22:36 +00:00
verifyWithArgsContractHash = "0dce75f52adb1a4c5c6eaa6a34eb26db2e5b3781"
2022-07-28 13:56:48 +00:00
nnsContractHash = "bdbfe1a280a0e23ca5b569c8f5845169bd93cb06"
2022-02-04 16:21:12 +00:00
nnsToken1ID = "6e656f2e636f6d"
2022-07-28 13:56:48 +00:00
nfsoContractHash = "0e15ca0df00669a2cd5dcb03bfd3e2b3849c2969"
2022-02-04 16:21:12 +00:00
nfsoToken1ID = "7e244ffd6aa85fb1579d2ed22e9b761ab62e3486"
invokescriptContractAVM = "VwIADBQBDAMOBQYMDQIODw0DDgcJAAAAAErZMCQE2zBwaEH4J+yMqiYEEUAMFA0PAwIJAAIBAwcDBAUCAQAOBgwJStkwJATbMHFpQfgn7IyqJgQSQBNA"
2022-08-11 13:08:26 +00:00
block20StateRootLE = "f1380226a217b5e35ea968d42c50e20b9af7ab83b91416c8fb85536c61004332"
2022-06-15 18:23:29 +00:00
storageContractHash = "ebc0c16a76c808cd4dde6bcc063f09e45e331ec7"
2022-02-04 16:21:12 +00:00
)
var (
nnsHash , _ = util . Uint160DecodeStringLE ( nnsContractHash )
nfsoHash , _ = util . Uint160DecodeStringLE ( nfsoContractHash )
nfsoToken1ContainerID = util . Uint256 { 1 , 2 , 3 }
nfsoToken1ObjectID = util . Uint256 { 4 , 5 , 6 }
)
2021-11-17 20:04:50 +00:00
2019-11-21 16:41:28 +00:00
var rpcTestCases = map [ string ] [ ] rpcTestCase {
2020-02-21 14:56:28 +00:00
"getapplicationlog" : {
{
name : "positive" ,
2020-06-18 09:00:51 +00:00
params : ` [" ` + deploymentTxHash + ` "] ` ,
2020-11-11 15:43:28 +00:00
result : func ( e * executor ) interface { } { return & result . ApplicationLog { } } ,
2020-02-21 14:56:28 +00:00
check : func ( t * testing . T , e * executor , acc interface { } ) {
2020-11-11 15:43:28 +00:00
res , ok := acc . ( * result . ApplicationLog )
2020-02-21 14:56:28 +00:00
require . True ( t , ok )
2020-06-18 09:00:51 +00:00
expectedTxHash , err := util . Uint256DecodeStringLE ( deploymentTxHash )
2020-03-04 14:45:29 +00:00
require . NoError ( t , err )
2020-11-11 15:43:28 +00:00
assert . Equal ( t , 1 , len ( res . Executions ) )
assert . Equal ( t , expectedTxHash , res . Container )
assert . Equal ( t , trigger . Application , res . Executions [ 0 ] . Trigger )
2022-07-08 14:28:29 +00:00
assert . Equal ( t , vmstate . Halt , res . Executions [ 0 ] . VMState )
2020-02-21 14:56:28 +00:00
} ,
} ,
2020-11-10 11:30:00 +00:00
{
name : "positive, genesis block" ,
params : ` [" ` + genesisBlockHash + ` "] ` ,
result : func ( e * executor ) interface { } { return & result . ApplicationLog { } } ,
check : func ( t * testing . T , e * executor , acc interface { } ) {
res , ok := acc . ( * result . ApplicationLog )
require . True ( t , ok )
assert . Equal ( t , genesisBlockHash , res . Container . StringLE ( ) )
2020-12-08 15:28:00 +00:00
assert . Equal ( t , 2 , len ( res . Executions ) )
assert . Equal ( t , trigger . OnPersist , res . Executions [ 0 ] . Trigger )
assert . Equal ( t , trigger . PostPersist , res . Executions [ 1 ] . Trigger )
2022-07-08 14:28:29 +00:00
assert . Equal ( t , vmstate . Halt , res . Executions [ 0 ] . VMState )
2020-11-10 11:30:00 +00:00
} ,
} ,
{
name : "positive, genesis block, postPersist" ,
params : ` [" ` + genesisBlockHash + ` ", "PostPersist"] ` ,
result : func ( e * executor ) interface { } { return & result . ApplicationLog { } } ,
check : func ( t * testing . T , e * executor , acc interface { } ) {
res , ok := acc . ( * result . ApplicationLog )
require . True ( t , ok )
assert . Equal ( t , genesisBlockHash , res . Container . StringLE ( ) )
assert . Equal ( t , 1 , len ( res . Executions ) )
2020-12-08 15:28:00 +00:00
assert . Equal ( t , trigger . PostPersist , res . Executions [ 0 ] . Trigger )
2022-07-08 14:28:29 +00:00
assert . Equal ( t , vmstate . Halt , res . Executions [ 0 ] . VMState )
2020-11-10 11:30:00 +00:00
} ,
} ,
{
name : "positive, genesis block, onPersist" ,
params : ` [" ` + genesisBlockHash + ` ", "OnPersist"] ` ,
result : func ( e * executor ) interface { } { return & result . ApplicationLog { } } ,
check : func ( t * testing . T , e * executor , acc interface { } ) {
res , ok := acc . ( * result . ApplicationLog )
require . True ( t , ok )
assert . Equal ( t , genesisBlockHash , res . Container . StringLE ( ) )
2020-12-08 15:28:00 +00:00
assert . Equal ( t , 1 , len ( res . Executions ) )
assert . Equal ( t , trigger . OnPersist , res . Executions [ 0 ] . Trigger )
2022-07-08 14:28:29 +00:00
assert . Equal ( t , vmstate . Halt , res . Executions [ 0 ] . VMState )
2020-02-21 14:56:28 +00:00
} ,
} ,
rpc: fix `getapplicationlog` RPC handler
Fixes the following panic:
```
2020/12/22 18:16:09 http: panic serving 127.0.0.1:50228: runtime error: invalid memory address or nil pointer dereference
goroutine 4043 [running]:
net/http.(*conn).serve.func1(0xc00094c960)
net/http/server.go:1772 +0x139
panic(0xcd9b40, 0x16a94e0)
runtime/panic.go:973 +0x396
github.com/nspcc-dev/neo-go/pkg/rpc/server.(*Server).getApplicationLog(0xc000094ea0, 0xc000472d20, 0x2, 0x4, 0xc0000be228, 0xc0007ad601, 0x28)
github.com/nspcc-dev/neo-go/pkg/rpc/server/server.go:542 +0xac
github.com/nspcc-dev/neo-go/pkg/rpc/server.(*Server).handleIn(0xc000094ea0, 0xc000089770, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
github.com/nspcc-dev/neo-go/pkg/rpc/server/server.go:326 +0x981
github.com/nspcc-dev/neo-go/pkg/rpc/server.(*Server).handleRequest(0xc000094ea0, 0xc001bccba0, 0x0, 0x0, 0x0)
github.com/nspcc-dev/neo-go/pkg/rpc/server/server.go:296 +0x26a
github.com/nspcc-dev/neo-go/pkg/rpc/server.(*Server).handleHTTPRequest(0xc000094ea0, 0x1071f40, 0xc000b089a0, 0xc00053c200)
github.com/nspcc-dev/neo-go/pkg/rpc/server/server.go:290 +0x91b
net/http.HandlerFunc.ServeHTTP(0xc0004e61b0, 0x1071f40, 0xc000b089a0, 0xc00053c200)
net/http/server.go:2012 +0x44
net/http.serverHandler.ServeHTTP(0xc0000d2ee0, 0x1071f40, 0xc000b089a0, 0xc00053c200)
net/http/server.go:2807 +0xa3
net/http.(*conn).serve(0xc00094c960, 0x10749c0, 0xc0006ae980)
net/http/server.go:1895 +0x86c
created by net/http.(*Server).Serve
net/http/server.go:2933 +0x35c
```
2020-12-22 15:21:04 +00:00
{
name : "invalid trigger (not a string)" ,
params : ` [" ` + genesisBlockHash + ` ", 1] ` ,
fail : true ,
} ,
2020-02-21 14:56:28 +00:00
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
{
name : "invalid address" ,
params : ` ["notahash"] ` ,
fail : true ,
} ,
{
name : "invalid tx hash" ,
params : ` ["d24cc1d52b5c0216cbf3835bb5bac8ccf32639fa1ab6627ec4e2b9f33f7ec02f"] ` ,
fail : true ,
} ,
} ,
2020-02-15 17:00:38 +00:00
"getcontractstate" : {
{
2020-09-25 09:40:57 +00:00
name : "positive, by hash" ,
2020-03-05 15:26:54 +00:00
params : fmt . Sprintf ( ` ["%s"] ` , testContractHash ) ,
2020-06-09 09:12:56 +00:00
result : func ( e * executor ) interface { } { return & state . Contract { } } ,
2020-02-21 12:10:59 +00:00
check : func ( t * testing . T , e * executor , cs interface { } ) {
2020-06-09 09:12:56 +00:00
res , ok := cs . ( * state . Contract )
2020-02-15 17:00:38 +00:00
require . True ( t , ok )
2020-11-18 20:10:48 +00:00
assert . Equal ( t , testContractHash , res . Hash . StringLE ( ) )
2020-02-15 17:00:38 +00:00
} ,
} ,
{
2020-09-25 09:40:57 +00:00
name : "positive, by id" ,
2021-01-15 21:17:31 +00:00
params : ` [1] ` ,
2020-09-25 09:40:57 +00:00
result : func ( e * executor ) interface { } { return & state . Contract { } } ,
check : func ( t * testing . T , e * executor , cs interface { } ) {
res , ok := cs . ( * state . Contract )
require . True ( t , ok )
2021-01-15 21:17:31 +00:00
assert . Equal ( t , int32 ( 1 ) , res . ID )
2020-09-25 09:40:57 +00:00
} ,
} ,
{
name : "positive, native by id" ,
params : ` [-3] ` ,
result : func ( e * executor ) interface { } { return & state . Contract { } } ,
check : func ( t * testing . T , e * executor , cs interface { } ) {
res , ok := cs . ( * state . Contract )
require . True ( t , ok )
assert . Equal ( t , int32 ( - 3 ) , res . ID )
} ,
} ,
{
name : "positive, native by name" ,
2020-12-13 18:25:04 +00:00
params : ` ["PolicyContract"] ` ,
2020-09-25 09:40:57 +00:00
result : func ( e * executor ) interface { } { return & state . Contract { } } ,
check : func ( t * testing . T , e * executor , cs interface { } ) {
res , ok := cs . ( * state . Contract )
require . True ( t , ok )
2021-02-15 15:43:10 +00:00
assert . Equal ( t , int32 ( - 7 ) , res . ID )
2020-09-25 09:40:57 +00:00
} ,
} ,
{
name : "negative, bad hash" ,
2020-02-15 17:00:38 +00:00
params : ` ["6d1eeca891ee93de2b7a77eb91c26f3b3c04d6c3"] ` ,
fail : true ,
} ,
2020-09-25 09:40:57 +00:00
{
name : "negative, bad ID" ,
2021-02-03 19:01:20 +00:00
params : ` [-100] ` ,
2020-09-25 09:40:57 +00:00
fail : true ,
} ,
{
name : "negative, bad native name" ,
params : ` ["unknown_native"] ` ,
fail : true ,
} ,
2020-02-15 17:00:38 +00:00
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
{
name : "invalid hash" ,
params : ` ["notahex"] ` ,
fail : true ,
} ,
} ,
2021-11-17 20:04:50 +00:00
"getnep11balances" : {
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
{
name : "invalid address" ,
params : ` ["notahex"] ` ,
fail : true ,
} ,
{
name : "positive" ,
params : ` [" ` + testchain . PrivateKeyByID ( 0 ) . GetScriptHash ( ) . StringLE ( ) + ` "] ` ,
2022-02-04 16:21:12 +00:00
result : func ( e * executor ) interface { } { return & result . NEP11Balances { } } ,
check : checkNep11Balances ,
2021-11-17 20:04:50 +00:00
} ,
{
name : "positive_address" ,
params : ` [" ` + address . Uint160ToString ( testchain . PrivateKeyByID ( 0 ) . GetScriptHash ( ) ) + ` "] ` ,
2022-02-04 16:21:12 +00:00
result : func ( e * executor ) interface { } { return & result . NEP11Balances { } } ,
check : checkNep11Balances ,
2021-11-17 20:04:50 +00:00
} ,
} ,
"getnep11properties" : {
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
{
name : "invalid address" ,
params : ` ["notahex"] ` ,
fail : true ,
} ,
{
name : "no token" ,
2022-02-04 16:21:12 +00:00
params : ` [" ` + nnsContractHash + ` "] ` ,
2021-11-17 20:04:50 +00:00
fail : true ,
} ,
{
name : "bad token" ,
2022-02-04 16:21:12 +00:00
params : ` [" ` + nnsContractHash + ` ", "abcdef"] ` ,
2021-11-17 20:04:50 +00:00
fail : true ,
} ,
{
name : "positive" ,
2022-02-04 16:21:12 +00:00
params : ` [" ` + nnsContractHash + ` ", "6e656f2e636f6d"] ` ,
2021-11-17 20:04:50 +00:00
result : func ( e * executor ) interface { } {
return & map [ string ] interface { } {
"name" : "neo.com" ,
2022-03-11 10:22:36 +00:00
"expiration" : "lhbLRl0B" ,
2021-11-17 20:04:50 +00:00
}
} ,
} ,
} ,
"getnep11transfers" : {
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
{
name : "invalid address" ,
params : ` ["notahex"] ` ,
fail : true ,
} ,
{
name : "invalid timestamp" ,
params : ` [" ` + testchain . PrivateKeyByID ( 0 ) . Address ( ) + ` ", "notanumber"] ` ,
fail : true ,
} ,
{
name : "invalid stop timestamp" ,
params : ` [" ` + testchain . PrivateKeyByID ( 0 ) . Address ( ) + ` ", "1", "blah"] ` ,
fail : true ,
} ,
{
name : "positive" ,
params : ` [" ` + testchain . PrivateKeyByID ( 0 ) . Address ( ) + ` ", 0] ` ,
2022-02-04 16:21:12 +00:00
result : func ( e * executor ) interface { } { return & result . NEP11Transfers { } } ,
check : checkNep11Transfers ,
2021-11-17 20:04:50 +00:00
} ,
} ,
2020-11-24 08:14:25 +00:00
"getnep17balances" : {
2020-03-05 11:50:06 +00:00
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
{
name : "invalid address" ,
params : ` ["notahex"] ` ,
fail : true ,
} ,
{
name : "positive" ,
2020-04-22 10:15:31 +00:00
params : ` [" ` + testchain . PrivateKeyByID ( 0 ) . GetScriptHash ( ) . StringLE ( ) + ` "] ` ,
2020-11-24 08:14:25 +00:00
result : func ( e * executor ) interface { } { return & result . NEP17Balances { } } ,
check : checkNep17Balances ,
2020-07-03 15:10:07 +00:00
} ,
{
name : "positive_address" ,
params : ` [" ` + address . Uint160ToString ( testchain . PrivateKeyByID ( 0 ) . GetScriptHash ( ) ) + ` "] ` ,
2020-11-24 08:14:25 +00:00
result : func ( e * executor ) interface { } { return & result . NEP17Balances { } } ,
check : checkNep17Balances ,
2020-03-05 11:50:06 +00:00
} ,
} ,
2020-11-24 08:14:25 +00:00
"getnep17transfers" : {
2020-03-05 12:16:03 +00:00
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
{
name : "invalid address" ,
params : ` ["notahex"] ` ,
fail : true ,
} ,
2020-08-07 06:42:44 +00:00
{
name : "invalid timestamp" ,
params : ` [" ` + testchain . PrivateKeyByID ( 0 ) . Address ( ) + ` ", "notanumber"] ` ,
fail : true ,
} ,
2020-09-12 21:12:45 +00:00
{
name : "invalid stop timestamp" ,
params : ` [" ` + testchain . PrivateKeyByID ( 0 ) . Address ( ) + ` ", "1", "blah"] ` ,
fail : true ,
} ,
{
name : "invalid limit" ,
params : ` [" ` + testchain . PrivateKeyByID ( 0 ) . Address ( ) + ` ", "1", "2", "0"] ` ,
fail : true ,
} ,
{
name : "invalid limit 2" ,
params : ` [" ` + testchain . PrivateKeyByID ( 0 ) . Address ( ) + ` ", "1", "2", "bleh"] ` ,
fail : true ,
} ,
2020-09-14 14:48:17 +00:00
{
name : "invalid limit 3" ,
params : ` [" ` + testchain . PrivateKeyByID ( 0 ) . Address ( ) + ` ", "1", "2", "100500"] ` ,
fail : true ,
} ,
2020-09-12 21:12:45 +00:00
{
name : "invalid page" ,
params : ` [" ` + testchain . PrivateKeyByID ( 0 ) . Address ( ) + ` ", "1", "2", "3", "-1"] ` ,
fail : true ,
} ,
{
name : "invalid page 2" ,
params : ` [" ` + testchain . PrivateKeyByID ( 0 ) . Address ( ) + ` ", "1", "2", "3", "jajaja"] ` ,
fail : true ,
} ,
2020-03-05 12:16:03 +00:00
{
name : "positive" ,
2020-08-07 06:42:44 +00:00
params : ` [" ` + testchain . PrivateKeyByID ( 0 ) . Address ( ) + ` ", 0] ` ,
2020-11-24 08:14:25 +00:00
result : func ( e * executor ) interface { } { return & result . NEP17Transfers { } } ,
check : checkNep17Transfers ,
2020-07-03 15:25:18 +00:00
} ,
{
name : "positive_hash" ,
2020-08-07 06:42:44 +00:00
params : ` [" ` + testchain . PrivateKeyByID ( 0 ) . GetScriptHash ( ) . StringLE ( ) + ` ", 0] ` ,
2020-11-24 08:14:25 +00:00
result : func ( e * executor ) interface { } { return & result . NEP17Transfers { } } ,
check : checkNep17Transfers ,
2020-03-05 12:16:03 +00:00
} ,
} ,
2020-06-04 08:59:22 +00:00
"getproof" : {
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
{
name : "invalid root" ,
params : ` ["0xabcdef"] ` ,
fail : true ,
} ,
{
name : "invalid contract" ,
params : ` ["0000000000000000000000000000000000000000000000000000000000000000", "0xabcdef"] ` ,
fail : true ,
} ,
{
name : "invalid key" ,
params : ` ["0000000000000000000000000000000000000000000000000000000000000000", " ` + testContractHash + ` ", "notahex"] ` ,
fail : true ,
} ,
} ,
2021-10-07 09:03:37 +00:00
"getstate" : {
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
{
name : "invalid root" ,
params : ` ["0xabcdef"] ` ,
fail : true ,
} ,
{
name : "invalid contract" ,
params : ` ["0000000000000000000000000000000000000000000000000000000000000000", "0xabcdef"] ` ,
fail : true ,
} ,
{
name : "invalid key" ,
params : ` ["0000000000000000000000000000000000000000000000000000000000000000", " ` + testContractHash + ` ", "notabase64%"] ` ,
fail : true ,
} ,
{
name : "unknown contract" ,
params : ` ["0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000", "QQ=="] ` ,
fail : true ,
} ,
{
name : "unknown root/item" ,
params : ` ["0000000000000000000000000000000000000000000000000000000000000000", " ` + testContractHash + ` ", "QQ=="] ` ,
fail : true ,
} ,
} ,
2021-10-07 13:56:27 +00:00
"findstates" : {
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
{
name : "invalid root" ,
params : ` ["0xabcdef"] ` ,
fail : true ,
} ,
{
name : "invalid contract" ,
params : ` ["0000000000000000000000000000000000000000000000000000000000000000", "0xabcdef"] ` ,
fail : true ,
} ,
{
name : "invalid prefix" ,
params : ` ["0000000000000000000000000000000000000000000000000000000000000000", " ` + testContractHash + ` ", "notabase64%"] ` ,
fail : true ,
} ,
{
name : "invalid key" ,
params : ` ["0000000000000000000000000000000000000000000000000000000000000000", " ` + testContractHash + ` ", "QQ==", "notabase64%"] ` ,
fail : true ,
} ,
{
name : "unknown contract/large count" ,
params : ` ["0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000", "QQ==", "QQ==", 101] ` ,
fail : true ,
} ,
} ,
2020-06-04 08:09:07 +00:00
"getstateheight" : {
{
name : "positive" ,
params : ` [] ` ,
result : func ( _ * executor ) interface { } { return new ( result . StateHeight ) } ,
check : func ( t * testing . T , e * executor , res interface { } ) {
sh , ok := res . ( * result . StateHeight )
require . True ( t , ok )
2021-07-22 16:55:41 +00:00
require . Equal ( t , e . chain . BlockHeight ( ) , sh . Local )
require . Equal ( t , uint32 ( 0 ) , sh . Validated )
2020-06-04 08:09:07 +00:00
} ,
} ,
} ,
2020-06-03 15:09:36 +00:00
"getstateroot" : {
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
{
name : "invalid hash" ,
params : ` ["0x1234567890"] ` ,
fail : true ,
} ,
} ,
2020-01-30 08:03:44 +00:00
"getstorage" : {
{
name : "positive" ,
2021-02-07 15:27:19 +00:00
params : fmt . Sprintf ( ` ["%s", "dGVzdGtleQ=="] ` , testContractHash ) ,
2020-02-21 12:10:59 +00:00
result : func ( e * executor ) interface { } {
2021-10-07 09:03:37 +00:00
v := base64 . StdEncoding . EncodeToString ( [ ] byte ( "newtestvalue" ) )
2020-02-21 12:10:59 +00:00
return & v
2020-01-30 08:03:44 +00:00
} ,
} ,
{
name : "missing key" ,
2021-02-07 15:27:19 +00:00
params : fmt . Sprintf ( ` ["%s", "dGU="] ` , testContractHash ) ,
2020-02-21 12:10:59 +00:00
result : func ( e * executor ) interface { } {
v := ""
return & v
2020-01-30 08:03:44 +00:00
} ,
} ,
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
{
name : "no second parameter" ,
2020-03-05 15:26:54 +00:00
params : fmt . Sprintf ( ` ["%s"] ` , testContractHash ) ,
2020-01-30 08:03:44 +00:00
fail : true ,
} ,
{
name : "invalid hash" ,
params : ` ["notahex"] ` ,
fail : true ,
} ,
{
name : "invalid key" ,
2021-02-07 15:27:19 +00:00
params : fmt . Sprintf ( ` ["%s", "notabase64$"] ` , testContractHash ) ,
2020-01-30 08:03:44 +00:00
fail : true ,
} ,
} ,
2019-11-21 16:41:28 +00:00
"getbestblockhash" : {
{
params : "[]" ,
result : func ( e * executor ) interface { } {
2020-02-21 12:10:59 +00:00
v := "0x" + e . chain . CurrentBlockHash ( ) . StringLE ( )
return & v
2019-11-21 16:41:28 +00:00
} ,
} ,
} ,
"getblock" : {
{
name : "positive" ,
2020-05-08 17:54:24 +00:00
params : "[3, 1]" ,
2020-06-18 09:00:51 +00:00
result : func ( _ * executor ) interface { } { return & result . Block { } } ,
2020-02-21 12:10:59 +00:00
check : func ( t * testing . T , e * executor , blockRes interface { } ) {
res , ok := blockRes . ( * result . Block )
2019-11-21 16:41:28 +00:00
require . True ( t , ok )
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
2020-05-08 17:54:24 +00:00
block , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 3 ) )
2019-11-21 16:41:28 +00:00
require . NoErrorf ( t , err , "could not get block" )
Implement rpc server method: sendrawtransaction (#174)
* Added new config attributes: 'SecondsPerBlock','LowPriorityThreshold'
* Added new files:
* Added new method: CompareTo
* Fixed empty Slice case
* Added new methods: LessThan, GreaterThan, Equal, CompareTo
* Added new method: InputIntersection
* Added MaxTransactionSize, GroupOutputByAssetID
* Added ned method: ScriptHash
* Added new method: IsDoubleSpend
* Refactor blockchainer, Added Feer interface, Verify and GetMemPool method
* 1) Added MemPool
2) Added new methods to satisfy the blockchainer interface: IsLowPriority, Verify, GetMemPool
* Added new methods: RelayTxn, RelayDirectly
* Fixed tests
* Implemented RPC server method sendrawtransaction
* Refactor getrawtransaction, sendrawtransaction in separate methods
* Moved 'secondsPerBlock' to config file
* Implemented Kim suggestions:
1) Fixed data race issues
2) refactor Verify method
3) Get rid of unused InputIntersection method due to refactoring Verify method
4) Fixed bug in https://github.com/CityOfZion/neo-go/pull/174#discussion_r264108135
5) minor simplications of the code
* Fixed minor issues related to
1) space
2) getter methods do not need pointer on the receiver
3) error message
4) refactoring CompareTo method in uint256.go
* Fixed small issues
* Use sync.RWMutex instead of sync.Mutex
* Refined (R)Lock/(R)Unlock
* return error instead of bool in Verify methods
2019-03-20 12:30:05 +00:00
2020-05-13 18:27:08 +00:00
assert . Equal ( t , block . Hash ( ) , res . Hash ( ) )
for i , tx := range res . Transactions {
2020-04-22 17:42:38 +00:00
actualTx := block . Transactions [ i ]
2020-02-12 14:25:44 +00:00
require . True ( t , ok )
2020-05-08 17:54:24 +00:00
require . Equal ( t , actualTx . Nonce , tx . Nonce )
require . Equal ( t , block . Transactions [ i ] . Hash ( ) , tx . Hash ( ) )
2020-02-12 14:25:44 +00:00
}
2019-11-21 16:41:28 +00:00
} ,
} ,
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
2019-11-26 10:31:11 +00:00
{
name : "bad params" ,
params : ` [[]] ` ,
fail : true ,
} ,
2019-11-21 16:41:28 +00:00
{
name : "invalid height" ,
params : ` [-1] ` ,
fail : true ,
} ,
{
name : "invalid hash" ,
params : ` ["notahex"] ` ,
fail : true ,
} ,
{
name : "missing hash" ,
params : ` [" ` + util . Uint256 { } . String ( ) + ` "] ` ,
fail : true ,
} ,
} ,
"getblockcount" : {
{
params : "[]" ,
2020-02-21 12:10:59 +00:00
result : func ( e * executor ) interface { } {
v := int ( e . chain . BlockHeight ( ) + 1 )
return & v
} ,
2019-11-21 16:41:28 +00:00
} ,
} ,
"getblockhash" : {
{
params : "[1]" ,
2020-02-21 12:10:59 +00:00
result : func ( e * executor ) interface { } {
// We don't have `t` here for proper handling, but
// error here would lead to panic down below.
block , _ := e . chain . GetBlock ( e . chain . GetHeaderHash ( 1 ) )
2019-11-27 09:23:18 +00:00
expectedHash := "0x" + block . Hash ( ) . StringLE ( )
2020-02-21 12:10:59 +00:00
return & expectedHash
2019-11-21 16:41:28 +00:00
} ,
} ,
{
name : "string height" ,
params : ` ["first"] ` ,
fail : true ,
} ,
{
name : "invalid number height" ,
params : ` [-2] ` ,
fail : true ,
} ,
} ,
2020-03-04 17:35:37 +00:00
"getblockheader" : {
{
name : "invalid verbose type" ,
2020-04-20 17:38:47 +00:00
params : ` ["9673799c5b5a294427401cb07d6cc615ada3a0d5c5bf7ed6f0f54f24abb2e2ac", true] ` ,
2020-03-04 17:35:37 +00:00
fail : true ,
} ,
{
name : "invalid block hash" ,
params : ` ["notahash"] ` ,
fail : true ,
} ,
{
name : "unknown block" ,
params : ` ["a6e526375a780335112299f2262501e5e9574c3ba61b16bbc1e282b344f6c141"] ` ,
fail : true ,
} ,
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
} ,
2021-02-07 19:01:22 +00:00
"getblockheadercount" : {
{
params : "[]" ,
result : func ( e * executor ) interface { } {
v := int ( e . chain . HeaderHeight ( ) + 1 )
return & v
} ,
} ,
} ,
2020-02-19 09:44:31 +00:00
"getblocksysfee" : {
{
name : "positive" ,
params : "[1]" ,
result : func ( e * executor ) interface { } {
block , _ := e . chain . GetBlock ( e . chain . GetHeaderHash ( 1 ) )
2020-06-23 14:15:35 +00:00
var expectedBlockSysFee int64
2020-02-19 09:44:31 +00:00
for _ , tx := range block . Transactions {
2020-05-08 17:54:24 +00:00
expectedBlockSysFee += tx . SystemFee
2020-02-19 09:44:31 +00:00
}
return & expectedBlockSysFee
} ,
} ,
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
{
name : "string height" ,
params : ` ["first"] ` ,
fail : true ,
} ,
{
name : "invalid number height" ,
params : ` [-2] ` ,
fail : true ,
2020-09-21 12:34:04 +00:00
} ,
} ,
"getcommittee" : {
{
params : "[]" ,
result : func ( e * executor ) interface { } {
2022-01-24 15:36:31 +00:00
expected , _ := e . chain . GetCommittee ( )
2020-09-21 12:34:04 +00:00
sort . Sort ( expected )
return & expected
} ,
2020-02-19 09:44:31 +00:00
} ,
} ,
2019-11-21 16:41:28 +00:00
"getconnectioncount" : {
{
params : "[]" ,
2020-02-21 12:10:59 +00:00
result : func ( * executor ) interface { } {
v := 0
return & v
} ,
2019-11-21 16:41:28 +00:00
} ,
} ,
2021-02-09 09:25:38 +00:00
"getnativecontracts" : {
{
params : "[]" ,
result : func ( e * executor ) interface { } {
return new ( [ ] state . NativeContract )
} ,
check : func ( t * testing . T , e * executor , res interface { } ) {
lst := res . ( * [ ] state . NativeContract )
for i := range * lst {
cs := e . chain . GetContractState ( ( * lst ) [ i ] . Hash )
require . NotNil ( t , cs )
require . True ( t , cs . ID <= 0 )
2021-03-11 11:39:51 +00:00
require . Equal ( t , [ ] uint32 { 0 } , ( * lst ) [ i ] . UpdateHistory )
2021-02-09 09:25:38 +00:00
}
} ,
} ,
} ,
2019-11-21 16:41:28 +00:00
"getpeers" : {
{
params : "[]" ,
result : func ( * executor ) interface { } {
2020-02-21 12:10:59 +00:00
return & result . GetPeers {
Unconnected : [ ] result . Peer { } ,
Connected : [ ] result . Peer { } ,
Bad : [ ] result . Peer { } ,
2019-11-21 16:41:28 +00:00
}
} ,
} ,
} ,
"getrawtransaction" : {
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
{
name : "invalid hash" ,
params : ` ["notahex"] ` ,
fail : true ,
} ,
{
name : "missing hash" ,
params : ` [" ` + util . Uint256 { } . String ( ) + ` "] ` ,
fail : true ,
} ,
} ,
2020-03-05 14:20:50 +00:00
"gettransactionheight" : {
{
2020-04-16 14:10:42 +00:00
name : "positive" ,
2020-06-18 09:00:51 +00:00
params : ` [" ` + deploymentTxHash + ` "] ` ,
2020-03-05 14:20:50 +00:00
result : func ( e * executor ) interface { } {
2020-06-04 19:21:12 +00:00
h := 0
2020-03-05 14:20:50 +00:00
return & h
} ,
2020-06-04 19:21:12 +00:00
check : func ( t * testing . T , e * executor , resp interface { } ) {
h , ok := resp . ( * int )
require . True ( t , ok )
assert . Equal ( t , 2 , * h )
} ,
2020-03-05 14:20:50 +00:00
} ,
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
{
name : "invalid hash" ,
params : ` ["notahex"] ` ,
fail : true ,
} ,
{
name : "missing hash" ,
params : ` [" ` + util . Uint256 { } . String ( ) + ` "] ` ,
fail : true ,
} ,
} ,
2020-06-01 20:27:03 +00:00
"getunclaimedgas" : {
2020-03-06 17:38:17 +00:00
{
name : "no params" ,
params : "[]" ,
fail : true ,
} ,
{
name : "invalid address" ,
params : ` ["invalid"] ` ,
fail : true ,
} ,
{
name : "positive" ,
2020-04-22 10:15:31 +00:00
params : ` [" ` + testchain . MultisigAddress ( ) + ` "] ` ,
2020-03-06 17:38:17 +00:00
result : func ( * executor ) interface { } {
2020-07-09 14:25:26 +00:00
return & result . UnclaimedGas { }
2020-03-06 17:38:17 +00:00
} ,
2020-06-01 20:27:03 +00:00
check : func ( t * testing . T , e * executor , resp interface { } ) {
2020-07-09 14:25:26 +00:00
actual , ok := resp . ( * result . UnclaimedGas )
2020-03-06 17:38:17 +00:00
require . True ( t , ok )
2020-07-09 14:25:26 +00:00
expected := result . UnclaimedGas {
Address : testchain . MultisigScriptHash ( ) ,
2022-06-15 18:23:29 +00:00
Unclaimed : * big . NewInt ( 11000 ) ,
2020-07-09 14:25:26 +00:00
}
assert . Equal ( t , expected , * actual )
2020-03-06 17:38:17 +00:00
} ,
} ,
} ,
2022-07-01 13:02:03 +00:00
"getcandidates" : {
{
params : "[]" ,
result : func ( * executor ) interface { } {
return & [ ] result . Candidate { }
} ,
} ,
} ,
2020-10-01 12:26:54 +00:00
"getnextblockvalidators" : {
2020-03-05 14:48:30 +00:00
{
params : "[]" ,
result : func ( * executor ) interface { } {
return & [ ] result . Validator { }
} ,
2020-08-10 14:51:46 +00:00
/ * preview3 doesn ' t return any validators until there is a vote
2020-03-05 14:48:30 +00:00
check : func ( t * testing . T , e * executor , validators interface { } ) {
var expected [ ] result . Validator
2020-06-23 15:15:55 +00:00
sBValidators := e . chain . GetStandByValidators ( )
2020-03-05 14:48:30 +00:00
for _ , sbValidator := range sBValidators {
expected = append ( expected , result . Validator {
PublicKey : * sbValidator ,
Votes : 0 ,
Active : true ,
} )
}
actual , ok := validators . ( * [ ] result . Validator )
require . True ( t , ok )
assert . ElementsMatch ( t , expected , * actual )
} ,
2020-08-10 14:51:46 +00:00
* /
2020-03-05 14:48:30 +00:00
} ,
} ,
2019-11-21 16:41:28 +00:00
"getversion" : {
{
params : "[]" ,
2020-02-21 12:10:59 +00:00
result : func ( * executor ) interface { } { return & result . Version { } } ,
check : func ( t * testing . T , e * executor , ver interface { } ) {
resp , ok := ver . ( * result . Version )
2019-11-21 16:41:28 +00:00
require . True ( t , ok )
2022-05-16 03:59:23 +00:00
require . Equal ( t , "/NEO-GO:0.98.6-test/" , resp . UserAgent )
2021-09-07 12:42:04 +00:00
cfg := e . chain . GetConfig ( )
require . EqualValues ( t , address . NEO3Prefix , resp . Protocol . AddressVersion )
require . EqualValues ( t , cfg . Magic , resp . Protocol . Network )
require . EqualValues ( t , cfg . SecondsPerBlock * 1000 , resp . Protocol . MillisecondsPerBlock )
require . EqualValues ( t , cfg . MaxTraceableBlocks , resp . Protocol . MaxTraceableBlocks )
require . EqualValues ( t , cfg . MaxValidUntilBlockIncrement , resp . Protocol . MaxValidUntilBlockIncrement )
require . EqualValues ( t , cfg . MaxTransactionsPerBlock , resp . Protocol . MaxTransactionsPerBlock )
require . EqualValues ( t , cfg . MemPoolSize , resp . Protocol . MemoryPoolMaxTransactions )
2021-09-28 07:10:26 +00:00
require . EqualValues ( t , cfg . ValidatorsCount , resp . Protocol . ValidatorsCount )
2021-09-07 12:42:04 +00:00
require . EqualValues ( t , cfg . InitialGASSupply , resp . Protocol . InitialGasDistribution )
2022-08-08 13:10:02 +00:00
require . Equal ( t , 0 , len ( resp . Protocol . CommitteeHistory ) )
require . True ( t , resp . Protocol . P2PSigExtensions ) // Yeah, notary is enabled.
require . False ( t , resp . Protocol . StateRootInHeader )
require . Equal ( t , 0 , len ( resp . Protocol . ValidatorsHistory ) )
2019-11-21 16:41:28 +00:00
} ,
} ,
} ,
2019-11-26 10:13:17 +00:00
"invokefunction" : {
2019-11-28 16:08:31 +00:00
{
name : "positive" ,
2019-11-26 10:13:17 +00:00
params : ` ["50befd26fdf6e4d957c11e078b24ebce6291456f", "test", []] ` ,
2020-03-03 10:08:34 +00:00
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
2020-02-21 12:10:59 +00:00
check : func ( t * testing . T , e * executor , inv interface { } ) {
2020-03-03 10:08:34 +00:00
res , ok := inv . ( * result . Invoke )
2019-11-28 16:08:31 +00:00
require . True ( t , ok )
2020-10-14 13:46:06 +00:00
assert . NotNil ( t , res . Script )
2020-02-21 12:10:59 +00:00
assert . NotEqual ( t , "" , res . State )
assert . NotEqual ( t , 0 , res . GasConsumed )
2019-11-28 16:08:31 +00:00
} ,
} ,
2022-01-18 19:35:44 +00:00
{
name : "positive, with notifications" ,
2022-02-04 16:21:12 +00:00
params : ` [" ` + nnsContractHash + ` ", "transfer", [ { "type":"Hash160", "value":"0x0bcd2978634d961c24f5aea0802297ff128724d6"}, { "type":"String", "value":"neo.com"}, { "type":"Any", "value":null}],["0xb248508f4ef7088e10c48f14d04be3272ca29eee"]] ` ,
2022-01-18 19:35:44 +00:00
result : func ( e * executor ) interface { } {
2022-07-28 13:56:48 +00:00
script := append ( [ ] byte { 0x0b , 0x0c , 0x07 , 0x6e , 0x65 , 0x6f , 0x2e , 0x63 , 0x6f , 0x6d , 0x0c , 0x14 , 0xd6 , 0x24 , 0x87 , 0x12 , 0xff , 0x97 , 0x22 , 0x80 , 0xa0 , 0xae , 0xf5 , 0x24 , 0x1c , 0x96 , 0x4d , 0x63 , 0x78 , 0x29 , 0xcd , 0xb , 0x13 , 0xc0 , 0x1f , 0xc , 0x8 , 0x74 , 0x72 , 0x61 , 0x6e , 0x73 , 0x66 , 0x65 , 0x72 , 0xc , 0x14 } , nnsHash . BytesBE ( ) ... )
script = append ( script , 0x41 , 0x62 , 0x7d , 0x5b , 0x52 )
2022-01-18 19:35:44 +00:00
return & result . Invoke {
State : "HALT" ,
2022-07-28 13:56:48 +00:00
GasConsumed : 32414250 ,
2022-01-18 19:35:44 +00:00
Script : script ,
Stack : [ ] stackitem . Item { stackitem . Make ( true ) } ,
Notifications : [ ] state . NotificationEvent { {
2022-02-04 16:21:12 +00:00
ScriptHash : nnsHash ,
2022-01-18 19:35:44 +00:00
Name : "Transfer" ,
Item : stackitem . NewArray ( [ ] stackitem . Item {
stackitem . Make ( [ ] byte { 0xee , 0x9e , 0xa2 , 0x2c , 0x27 , 0xe3 , 0x4b , 0xd0 , 0x14 , 0x8f , 0xc4 , 0x10 , 0x8e , 0x08 , 0xf7 , 0x4e , 0x8f , 0x50 , 0x48 , 0xb2 } ) ,
stackitem . Make ( [ ] byte { 0xd6 , 0x24 , 0x87 , 0x12 , 0xff , 0x97 , 0x22 , 0x80 , 0xa0 , 0xae , 0xf5 , 0x24 , 0x1c , 0x96 , 0x4d , 0x63 , 0x78 , 0x29 , 0xcd , 0x0b } ) ,
stackitem . Make ( 1 ) ,
stackitem . Make ( "neo.com" ) ,
} ) ,
} } ,
}
} ,
} ,
2022-01-18 21:02:19 +00:00
{
name : "positive, with storage changes" ,
params : ` ["0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5", "transfer", [ { "type":"Hash160", "value":"0xb248508f4ef7088e10c48f14d04be3272ca29eee"}, { "type":"Hash160", "value":"0x0bcd2978634d961c24f5aea0802297ff128724d6"}, { "type":"Integer", "value":1}, { "type":"Any", "value":null}],["0xb248508f4ef7088e10c48f14d04be3272ca29eee"],true] ` ,
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
assert . NotNil ( t , res . Script )
assert . Equal ( t , "HALT" , res . State )
assert . Equal ( t , [ ] stackitem . Item { stackitem . Make ( true ) } , res . Stack )
assert . NotEqual ( t , 0 , res . GasConsumed )
2022-07-08 18:17:52 +00:00
chg := [ ] dboper . Operation { {
2022-01-18 21:02:19 +00:00
State : "Changed" ,
Key : [ ] byte { 0xfa , 0xff , 0xff , 0xff , 0xb } ,
2022-07-28 13:56:48 +00:00
Value : [ ] byte { 0xf6 , 0x8b , 0x4e , 0x9d , 0x51 , 0x79 , 0x12 } ,
2022-01-18 21:02:19 +00:00
} , {
State : "Added" ,
Key : [ ] byte { 0xfb , 0xff , 0xff , 0xff , 0x14 , 0xd6 , 0x24 , 0x87 , 0x12 , 0xff , 0x97 , 0x22 , 0x80 , 0xa0 , 0xae , 0xf5 , 0x24 , 0x1c , 0x96 , 0x4d , 0x63 , 0x78 , 0x29 , 0xcd , 0xb } ,
2022-06-15 18:23:29 +00:00
Value : [ ] byte { 0x41 , 0x03 , 0x21 , 0x01 , 0x01 , 0x21 , 0x01 , 0x17 , 0 } ,
2022-01-18 21:02:19 +00:00
} , {
State : "Changed" ,
Key : [ ] byte { 0xfb , 0xff , 0xff , 0xff , 0x14 , 0xee , 0x9e , 0xa2 , 0x2c , 0x27 , 0xe3 , 0x4b , 0xd0 , 0x14 , 0x8f , 0xc4 , 0x10 , 0x8e , 0x8 , 0xf7 , 0x4e , 0x8f , 0x50 , 0x48 , 0xb2 } ,
2022-06-15 18:23:29 +00:00
Value : [ ] byte { 0x41 , 0x03 , 0x21 , 0x04 , 0x2f , 0xd9 , 0xf5 , 0x05 , 0x21 , 0x01 , 0x17 , 0 } ,
2022-01-18 21:02:19 +00:00
} , {
State : "Changed" ,
Key : [ ] byte { 0xfa , 0xff , 0xff , 0xff , 0x14 , 0xee , 0x9e , 0xa2 , 0x2c , 0x27 , 0xe3 , 0x4b , 0xd0 , 0x14 , 0x8f , 0xc4 , 0x10 , 0x8e , 0x8 , 0xf7 , 0x4e , 0x8f , 0x50 , 0x48 , 0xb2 } ,
2022-07-28 13:56:48 +00:00
Value : [ ] byte { 0x41 , 0x01 , 0x21 , 0x05 , 0xe4 , 0x74 , 0xef , 0xdb , 0x08 } ,
2022-01-18 21:02:19 +00:00
} }
// Can be returned in any order.
assert . ElementsMatch ( t , chg , res . Diagnostics . Changes )
} ,
} ,
2021-11-20 18:55:55 +00:00
{
name : "positive, verbose" ,
2022-02-04 16:21:12 +00:00
params : ` [" ` + nnsContractHash + ` ", "resolve", [ { "type":"String", "value":"neo.com"}, { "type":"Integer","value":1}], [], true] ` ,
2021-11-20 18:55:55 +00:00
result : func ( e * executor ) interface { } {
2022-07-28 13:56:48 +00:00
script := append ( [ ] byte { 0x11 , 0xc , 0x7 , 0x6e , 0x65 , 0x6f , 0x2e , 0x63 , 0x6f , 0x6d , 0x12 , 0xc0 , 0x1f , 0xc , 0x7 , 0x72 , 0x65 , 0x73 , 0x6f , 0x6c , 0x76 , 0x65 , 0xc , 0x14 } , nnsHash . BytesBE ( ) ... )
script = append ( script , 0x41 , 0x62 , 0x7d , 0x5b , 0x52 )
2021-11-20 18:55:55 +00:00
stdHash , _ := e . chain . GetNativeContractScriptHash ( nativenames . StdLib )
cryptoHash , _ := e . chain . GetNativeContractScriptHash ( nativenames . CryptoLib )
return & result . Invoke {
2022-01-18 19:35:44 +00:00
State : "HALT" ,
2022-02-04 16:21:12 +00:00
GasConsumed : 15928320 ,
2022-01-18 19:35:44 +00:00
Script : script ,
Stack : [ ] stackitem . Item { stackitem . Make ( "1.2.3.4" ) } ,
Notifications : [ ] state . NotificationEvent { } ,
2021-11-20 18:55:55 +00:00
Diagnostics : & result . InvokeDiag {
2022-07-08 18:17:52 +00:00
Changes : [ ] dboper . Operation { } ,
2022-07-08 17:49:21 +00:00
Invocations : [ ] * invocations . Tree { {
2021-11-20 18:55:55 +00:00
Current : hash . Hash160 ( script ) ,
2022-07-08 17:49:21 +00:00
Calls : [ ] * invocations . Tree {
2021-11-20 18:55:55 +00:00
{
2022-02-04 16:21:12 +00:00
Current : nnsHash ,
2022-07-08 17:49:21 +00:00
Calls : [ ] * invocations . Tree {
2021-11-20 18:55:55 +00:00
{
Current : stdHash ,
} ,
{
Current : cryptoHash ,
} ,
{
Current : stdHash ,
} ,
{
Current : cryptoHash ,
} ,
{
Current : cryptoHash ,
} ,
} ,
} ,
} ,
} } ,
} ,
}
} ,
} ,
2019-11-28 16:08:31 +00:00
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
{
name : "not a string" ,
2019-11-26 10:13:17 +00:00
params : ` [42, "test", []] ` ,
2019-11-28 16:08:31 +00:00
fail : true ,
} ,
{
name : "not a scripthash" ,
2019-11-26 10:13:17 +00:00
params : ` ["qwerty", "test", []] ` ,
2019-11-28 16:08:31 +00:00
fail : true ,
} ,
{
name : "bad params" ,
2019-11-26 10:13:17 +00:00
params : ` ["50befd26fdf6e4d957c11e078b24ebce6291456f", "test", [ { "type": "Integer", "value": "qwerty"}]] ` ,
2019-11-28 16:08:31 +00:00
fail : true ,
} ,
} ,
2022-04-07 15:13:08 +00:00
"invokefunctionhistoric" : {
{
name : "positive, by index" ,
params : ` [20, "50befd26fdf6e4d957c11e078b24ebce6291456f", "test", []] ` ,
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
assert . NotNil ( t , res . Script )
assert . NotEqual ( t , "" , res . State )
assert . NotEqual ( t , 0 , res . GasConsumed )
} ,
} ,
{
name : "positive, by stateroot" ,
params : ` [" ` + block20StateRootLE + ` ", "50befd26fdf6e4d957c11e078b24ebce6291456f", "test", []] ` ,
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
assert . NotNil ( t , res . Script )
assert . NotEqual ( t , "" , res . State )
assert . NotEqual ( t , 0 , res . GasConsumed )
} ,
} ,
{
name : "positive, with notifications" ,
params : ` [20, " ` + nnsContractHash + ` ", "transfer", [ { "type":"Hash160", "value":"0x0bcd2978634d961c24f5aea0802297ff128724d6"}, { "type":"String", "value":"neo.com"}, { "type":"Any", "value":null}],["0xb248508f4ef7088e10c48f14d04be3272ca29eee"]] ` ,
result : func ( e * executor ) interface { } {
2022-07-28 13:56:48 +00:00
script := append ( [ ] byte { 0x0b , 0x0c , 0x07 , 0x6e , 0x65 , 0x6f , 0x2e , 0x63 , 0x6f , 0x6d , 0x0c , 0x14 , 0xd6 , 0x24 , 0x87 , 0x12 , 0xff , 0x97 , 0x22 , 0x80 , 0xa0 , 0xae , 0xf5 , 0x24 , 0x1c , 0x96 , 0x4d , 0x63 , 0x78 , 0x29 , 0xcd , 0xb , 0x13 , 0xc0 , 0x1f , 0xc , 0x8 , 0x74 , 0x72 , 0x61 , 0x6e , 0x73 , 0x66 , 0x65 , 0x72 , 0xc , 0x14 } , nnsHash . BytesBE ( ) ... )
script = append ( script , 0x41 , 0x62 , 0x7d , 0x5b , 0x52 )
2022-04-07 15:13:08 +00:00
return & result . Invoke {
State : "HALT" ,
2022-07-28 13:56:48 +00:00
GasConsumed : 32414250 ,
2022-04-07 15:13:08 +00:00
Script : script ,
Stack : [ ] stackitem . Item { stackitem . Make ( true ) } ,
Notifications : [ ] state . NotificationEvent { {
ScriptHash : nnsHash ,
Name : "Transfer" ,
Item : stackitem . NewArray ( [ ] stackitem . Item {
stackitem . Make ( [ ] byte { 0xee , 0x9e , 0xa2 , 0x2c , 0x27 , 0xe3 , 0x4b , 0xd0 , 0x14 , 0x8f , 0xc4 , 0x10 , 0x8e , 0x08 , 0xf7 , 0x4e , 0x8f , 0x50 , 0x48 , 0xb2 } ) ,
stackitem . Make ( [ ] byte { 0xd6 , 0x24 , 0x87 , 0x12 , 0xff , 0x97 , 0x22 , 0x80 , 0xa0 , 0xae , 0xf5 , 0x24 , 0x1c , 0x96 , 0x4d , 0x63 , 0x78 , 0x29 , 0xcd , 0x0b } ) ,
stackitem . Make ( 1 ) ,
stackitem . Make ( "neo.com" ) ,
} ) ,
} } ,
}
} ,
} ,
{
name : "positive, verbose" ,
params : ` [20, " ` + nnsContractHash + ` ", "resolve", [ { "type":"String", "value":"neo.com"}, { "type":"Integer","value":1}], [], true] ` ,
result : func ( e * executor ) interface { } {
2022-07-28 13:56:48 +00:00
script := append ( [ ] byte { 0x11 , 0xc , 0x7 , 0x6e , 0x65 , 0x6f , 0x2e , 0x63 , 0x6f , 0x6d , 0x12 , 0xc0 , 0x1f , 0xc , 0x7 , 0x72 , 0x65 , 0x73 , 0x6f , 0x6c , 0x76 , 0x65 , 0xc , 0x14 } , nnsHash . BytesBE ( ) ... )
script = append ( script , 0x41 , 0x62 , 0x7d , 0x5b , 0x52 )
2022-04-07 15:13:08 +00:00
stdHash , _ := e . chain . GetNativeContractScriptHash ( nativenames . StdLib )
cryptoHash , _ := e . chain . GetNativeContractScriptHash ( nativenames . CryptoLib )
return & result . Invoke {
State : "HALT" ,
GasConsumed : 15928320 ,
Script : script ,
Stack : [ ] stackitem . Item { stackitem . Make ( "1.2.3.4" ) } ,
Notifications : [ ] state . NotificationEvent { } ,
Diagnostics : & result . InvokeDiag {
2022-07-08 18:17:52 +00:00
Changes : [ ] dboper . Operation { } ,
2022-07-08 17:49:21 +00:00
Invocations : [ ] * invocations . Tree { {
2022-04-07 15:13:08 +00:00
Current : hash . Hash160 ( script ) ,
2022-07-08 17:49:21 +00:00
Calls : [ ] * invocations . Tree {
2022-04-07 15:13:08 +00:00
{
Current : nnsHash ,
2022-07-08 17:49:21 +00:00
Calls : [ ] * invocations . Tree {
2022-04-07 15:13:08 +00:00
{
Current : stdHash ,
} ,
{
Current : cryptoHash ,
} ,
{
Current : stdHash ,
} ,
{
Current : cryptoHash ,
} ,
{
Current : cryptoHash ,
} ,
} ,
} ,
} ,
} } ,
} ,
}
} ,
} ,
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
{
name : "no args" ,
params : ` [20] ` ,
fail : true ,
} ,
{
name : "not a string" ,
params : ` [20, 42, "test", []] ` ,
fail : true ,
} ,
{
name : "not a scripthash" ,
params : ` [20,"qwerty", "test", []] ` ,
fail : true ,
} ,
{
name : "bad params" ,
params : ` [20,"50befd26fdf6e4d957c11e078b24ebce6291456f", "test", [ { "type": "Integer", "value": "qwerty"}]] ` ,
fail : true ,
} ,
{
name : "bad height" ,
params : ` [100500,"50befd26fdf6e4d957c11e078b24ebce6291456f", "test", [ { "type": "Integer", "value": 1}]] ` ,
fail : true ,
} ,
{
name : "bad stateroot" ,
params : ` [" ` + util . Uint256 { 1 , 2 , 3 } . StringLE ( ) + ` ","50befd26fdf6e4d957c11e078b24ebce6291456f", "test", [ { "type": "Integer", "value": 1}]] ` ,
fail : true ,
} ,
} ,
2019-11-26 10:24:49 +00:00
"invokescript" : {
2019-11-26 10:13:17 +00:00
{
name : "positive" ,
2020-10-14 13:46:06 +00:00
params : ` ["UcVrDUhlbGxvLCB3b3JsZCFoD05lby5SdW50aW1lLkxvZ2FsdWY="] ` ,
2020-03-03 10:08:34 +00:00
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
2020-02-21 12:10:59 +00:00
check : func ( t * testing . T , e * executor , inv interface { } ) {
2020-03-03 10:08:34 +00:00
res , ok := inv . ( * result . Invoke )
2019-11-26 10:13:17 +00:00
require . True ( t , ok )
2020-02-21 12:10:59 +00:00
assert . NotEqual ( t , "" , res . Script )
assert . NotEqual ( t , "" , res . State )
assert . NotEqual ( t , 0 , res . GasConsumed )
2019-11-26 10:13:17 +00:00
} ,
} ,
2021-11-20 18:55:55 +00:00
{
name : "positive,verbose" ,
params : ` ["UcVrDUhlbGxvLCB3b3JsZCFoD05lby5SdW50aW1lLkxvZ2FsdWY=",[],true] ` ,
result : func ( e * executor ) interface { } {
script := [ ] byte { 0x51 , 0xc5 , 0x6b , 0xd , 0x48 , 0x65 , 0x6c , 0x6c , 0x6f , 0x2c , 0x20 , 0x77 , 0x6f , 0x72 , 0x6c , 0x64 , 0x21 , 0x68 , 0xf , 0x4e , 0x65 , 0x6f , 0x2e , 0x52 , 0x75 , 0x6e , 0x74 , 0x69 , 0x6d , 0x65 , 0x2e , 0x4c , 0x6f , 0x67 , 0x61 , 0x6c , 0x75 , 0x66 }
return & result . Invoke {
State : "FAULT" ,
GasConsumed : 60 ,
Script : script ,
Stack : [ ] stackitem . Item { } ,
FaultException : "at instruction 0 (ROT): too big index" ,
2022-01-18 19:35:44 +00:00
Notifications : [ ] state . NotificationEvent { } ,
2021-11-20 18:55:55 +00:00
Diagnostics : & result . InvokeDiag {
2022-07-08 18:17:52 +00:00
Changes : [ ] dboper . Operation { } ,
2022-07-08 17:49:21 +00:00
Invocations : [ ] * invocations . Tree { {
2021-11-20 18:55:55 +00:00
Current : hash . Hash160 ( script ) ,
} } ,
} ,
}
} ,
} ,
2019-11-26 10:13:17 +00:00
{
2020-06-10 11:45:55 +00:00
name : "positive, good witness" ,
2021-03-05 07:18:03 +00:00
// script is base64-encoded `invokescript_contract.avm` representation, hashes are hex-encoded LE bytes of hashes used in the contract with `0x` prefix
params : fmt . Sprintf ( ` ["%s",["0x0000000009070e030d0f0e020d0c06050e030c01","0x090c060e00010205040307030102000902030f0d"]] ` , invokescriptContractAVM ) ,
2020-06-10 11:45:55 +00:00
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
assert . Equal ( t , "HALT" , res . State )
require . Equal ( t , 1 , len ( res . Stack ) )
2020-07-31 12:26:28 +00:00
require . Equal ( t , big . NewInt ( 3 ) , res . Stack [ 0 ] . Value ( ) )
2020-06-10 11:45:55 +00:00
} ,
2019-11-26 10:13:17 +00:00
} ,
{
2020-06-10 11:45:55 +00:00
name : "positive, bad witness of second hash" ,
2021-03-05 07:18:03 +00:00
params : fmt . Sprintf ( ` ["%s",["0x0000000009070e030d0f0e020d0c06050e030c01"]] ` , invokescriptContractAVM ) ,
2020-06-10 11:45:55 +00:00
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
assert . Equal ( t , "HALT" , res . State )
require . Equal ( t , 1 , len ( res . Stack ) )
2020-07-31 12:26:28 +00:00
require . Equal ( t , big . NewInt ( 2 ) , res . Stack [ 0 ] . Value ( ) )
2020-06-10 11:45:55 +00:00
} ,
2019-11-26 10:13:17 +00:00
} ,
{
2020-06-10 11:45:55 +00:00
name : "positive, no good hashes" ,
2021-03-05 07:18:03 +00:00
params : fmt . Sprintf ( ` ["%s"] ` , invokescriptContractAVM ) ,
2020-06-10 11:45:55 +00:00
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
assert . Equal ( t , "HALT" , res . State )
require . Equal ( t , 1 , len ( res . Stack ) )
2020-07-31 12:26:28 +00:00
require . Equal ( t , big . NewInt ( 1 ) , res . Stack [ 0 ] . Value ( ) )
2020-06-10 11:45:55 +00:00
} ,
2019-11-26 10:13:17 +00:00
} ,
2019-11-26 10:24:49 +00:00
{
2020-06-10 11:45:55 +00:00
name : "positive, bad hashes witness" ,
2021-03-05 07:18:03 +00:00
params : fmt . Sprintf ( ` ["%s",["0x0000000009070e030d0f0e020d0c06050e030c02"]] ` , invokescriptContractAVM ) ,
2020-03-03 10:08:34 +00:00
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
2020-02-21 12:10:59 +00:00
check : func ( t * testing . T , e * executor , inv interface { } ) {
2020-03-03 10:08:34 +00:00
res , ok := inv . ( * result . Invoke )
2019-11-26 10:24:49 +00:00
require . True ( t , ok )
2020-06-10 11:45:55 +00:00
assert . Equal ( t , "HALT" , res . State )
assert . Equal ( t , 1 , len ( res . Stack ) )
2020-07-31 12:26:28 +00:00
assert . Equal ( t , big . NewInt ( 1 ) , res . Stack [ 0 ] . Value ( ) )
2019-11-26 10:24:49 +00:00
} ,
} ,
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
{
name : "not a string" ,
params : ` [42] ` ,
fail : true ,
} ,
{
name : "bas string" ,
params : ` ["qwerty"] ` ,
fail : true ,
} ,
} ,
2022-04-07 15:13:08 +00:00
"invokescripthistoric" : {
{
name : "positive, by index" ,
params : ` [20,"UcVrDUhlbGxvLCB3b3JsZCFoD05lby5SdW50aW1lLkxvZ2FsdWY="] ` ,
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
assert . NotEqual ( t , "" , res . Script )
assert . NotEqual ( t , "" , res . State )
assert . NotEqual ( t , 0 , res . GasConsumed )
} ,
} ,
{
name : "positive, by stateroot" ,
params : ` [" ` + block20StateRootLE + ` ","UcVrDUhlbGxvLCB3b3JsZCFoD05lby5SdW50aW1lLkxvZ2FsdWY="] ` ,
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
assert . NotEqual ( t , "" , res . Script )
assert . NotEqual ( t , "" , res . State )
assert . NotEqual ( t , 0 , res . GasConsumed )
} ,
} ,
{
name : "positive,verbose" ,
params : ` [20, "UcVrDUhlbGxvLCB3b3JsZCFoD05lby5SdW50aW1lLkxvZ2FsdWY=",[],true] ` ,
result : func ( e * executor ) interface { } {
script := [ ] byte { 0x51 , 0xc5 , 0x6b , 0xd , 0x48 , 0x65 , 0x6c , 0x6c , 0x6f , 0x2c , 0x20 , 0x77 , 0x6f , 0x72 , 0x6c , 0x64 , 0x21 , 0x68 , 0xf , 0x4e , 0x65 , 0x6f , 0x2e , 0x52 , 0x75 , 0x6e , 0x74 , 0x69 , 0x6d , 0x65 , 0x2e , 0x4c , 0x6f , 0x67 , 0x61 , 0x6c , 0x75 , 0x66 }
return & result . Invoke {
State : "FAULT" ,
GasConsumed : 60 ,
Script : script ,
Stack : [ ] stackitem . Item { } ,
FaultException : "at instruction 0 (ROT): too big index" ,
Notifications : [ ] state . NotificationEvent { } ,
Diagnostics : & result . InvokeDiag {
2022-07-08 18:17:52 +00:00
Changes : [ ] dboper . Operation { } ,
2022-07-08 17:49:21 +00:00
Invocations : [ ] * invocations . Tree { {
2022-04-07 15:13:08 +00:00
Current : hash . Hash160 ( script ) ,
} } ,
} ,
}
} ,
} ,
{
name : "positive, good witness" ,
// script is base64-encoded `invokescript_contract.avm` representation, hashes are hex-encoded LE bytes of hashes used in the contract with `0x` prefix
params : fmt . Sprintf ( ` [20,"%s",["0x0000000009070e030d0f0e020d0c06050e030c01","0x090c060e00010205040307030102000902030f0d"]] ` , invokescriptContractAVM ) ,
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
assert . Equal ( t , "HALT" , res . State )
require . Equal ( t , 1 , len ( res . Stack ) )
require . Equal ( t , big . NewInt ( 3 ) , res . Stack [ 0 ] . Value ( ) )
} ,
} ,
{
name : "positive, bad witness of second hash" ,
params : fmt . Sprintf ( ` [20,"%s",["0x0000000009070e030d0f0e020d0c06050e030c01"]] ` , invokescriptContractAVM ) ,
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
assert . Equal ( t , "HALT" , res . State )
require . Equal ( t , 1 , len ( res . Stack ) )
require . Equal ( t , big . NewInt ( 2 ) , res . Stack [ 0 ] . Value ( ) )
} ,
} ,
{
name : "positive, no good hashes" ,
params : fmt . Sprintf ( ` [20,"%s"] ` , invokescriptContractAVM ) ,
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
assert . Equal ( t , "HALT" , res . State )
require . Equal ( t , 1 , len ( res . Stack ) )
require . Equal ( t , big . NewInt ( 1 ) , res . Stack [ 0 ] . Value ( ) )
} ,
} ,
{
name : "positive, bad hashes witness" ,
params : fmt . Sprintf ( ` [20,"%s",["0x0000000009070e030d0f0e020d0c06050e030c02"]] ` , invokescriptContractAVM ) ,
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
assert . Equal ( t , "HALT" , res . State )
assert . Equal ( t , 1 , len ( res . Stack ) )
assert . Equal ( t , big . NewInt ( 1 ) , res . Stack [ 0 ] . Value ( ) )
} ,
} ,
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
{
name : "no script" ,
params : ` [20] ` ,
fail : true ,
} ,
{
name : "not a string" ,
params : ` [20,42] ` ,
fail : true ,
} ,
{
name : "bas string" ,
params : ` [20, "qwerty"] ` ,
fail : true ,
} ,
{
name : "bas height" ,
params : ` [100500,"qwerty"] ` ,
fail : true ,
} ,
{
name : "bas stateroot" ,
params : ` [" ` + util . Uint256 { 1 , 2 , 3 } . StringLE ( ) + ` ","UcVrDUhlbGxvLCB3b3JsZCFoD05lby5SdW50aW1lLkxvZ2FsdWY="] ` ,
fail : true ,
} ,
} ,
2020-12-14 12:23:39 +00:00
"invokecontractverify" : {
{
name : "positive" ,
params : fmt . Sprintf ( ` ["%s", [], [ { "account":"%s"}]] ` , verifyContractHash , testchain . PrivateKeyByID ( 0 ) . PublicKey ( ) . GetScriptHash ( ) . StringLE ( ) ) ,
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
2021-03-10 14:43:52 +00:00
assert . Nil ( t , res . Script ) // empty witness invocation script (pushes args of `verify` on stack, but this `verify` don't have args)
2020-12-14 12:23:39 +00:00
assert . Equal ( t , "HALT" , res . State )
assert . NotEqual ( t , 0 , res . GasConsumed )
2021-03-05 07:18:03 +00:00
assert . Equal ( t , true , res . Stack [ 0 ] . Value ( ) . ( bool ) , fmt . Sprintf ( "check address in verification_contract.go: expected %s" , testchain . PrivateKeyByID ( 0 ) . Address ( ) ) )
2020-12-14 12:23:39 +00:00
} ,
} ,
{
name : "positive, no signers" ,
params : fmt . Sprintf ( ` ["%s", []] ` , verifyContractHash ) ,
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
2021-03-10 14:43:52 +00:00
assert . Nil ( t , res . Script )
assert . Equal ( t , "HALT" , res . State , res . FaultException )
assert . NotEqual ( t , 0 , res . GasConsumed )
assert . Equal ( t , false , res . Stack [ 0 ] . Value ( ) . ( bool ) )
} ,
} ,
{
name : "positive, no arguments" ,
params : fmt . Sprintf ( ` ["%s"] ` , verifyContractHash ) ,
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
assert . Nil ( t , res . Script )
2020-12-14 12:23:39 +00:00
assert . Equal ( t , "HALT" , res . State , res . FaultException )
assert . NotEqual ( t , 0 , res . GasConsumed )
assert . Equal ( t , false , res . Stack [ 0 ] . Value ( ) . ( bool ) )
} ,
} ,
{
2021-03-10 14:43:52 +00:00
name : "positive, with signers and scripts" ,
2020-12-14 12:23:39 +00:00
params : fmt . Sprintf ( ` ["%s", [], [ { "account":"%s", "invocation":"MQo=", "verification": ""}]] ` , verifyContractHash , testchain . PrivateKeyByID ( 0 ) . PublicKey ( ) . GetScriptHash ( ) . StringLE ( ) ) ,
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
2021-03-10 14:43:52 +00:00
assert . Nil ( t , res . Script )
2020-12-14 12:23:39 +00:00
assert . Equal ( t , "HALT" , res . State )
assert . NotEqual ( t , 0 , res . GasConsumed )
assert . Equal ( t , true , res . Stack [ 0 ] . Value ( ) . ( bool ) )
} ,
} ,
2021-03-10 14:43:52 +00:00
{
name : "positive, with arguments, result=true" ,
2021-05-25 08:24:28 +00:00
params : fmt . Sprintf ( ` ["%s", [ { "type": "String", "value": "good_string"}, { "type": "Integer", "value": "4"}, { "type":"Boolean", "value": false}]] ` , verifyWithArgsContractHash ) ,
2021-03-10 14:43:52 +00:00
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
expectedInvScript := io . NewBufBinWriter ( )
emit . Int ( expectedInvScript . BinWriter , 0 )
emit . Int ( expectedInvScript . BinWriter , int64 ( 4 ) )
emit . String ( expectedInvScript . BinWriter , "good_string" )
require . NoError ( t , expectedInvScript . Err )
assert . Equal ( t , expectedInvScript . Bytes ( ) , res . Script ) // witness invocation script (pushes args of `verify` on stack)
assert . Equal ( t , "HALT" , res . State , res . FaultException )
assert . NotEqual ( t , 0 , res . GasConsumed )
assert . Equal ( t , true , res . Stack [ 0 ] . Value ( ) . ( bool ) )
} ,
} ,
{
name : "positive, with arguments, result=false" ,
2021-05-25 08:24:28 +00:00
params : fmt . Sprintf ( ` ["%s", [ { "type": "String", "value": "invalid_string"}, { "type": "Integer", "value": "4"}, { "type":"Boolean", "value": false}]] ` , verifyWithArgsContractHash ) ,
2021-03-10 14:43:52 +00:00
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
expectedInvScript := io . NewBufBinWriter ( )
emit . Int ( expectedInvScript . BinWriter , 0 )
emit . Int ( expectedInvScript . BinWriter , int64 ( 4 ) )
emit . String ( expectedInvScript . BinWriter , "invalid_string" )
require . NoError ( t , expectedInvScript . Err )
assert . Equal ( t , expectedInvScript . Bytes ( ) , res . Script )
assert . Equal ( t , "HALT" , res . State , res . FaultException )
assert . NotEqual ( t , 0 , res . GasConsumed )
assert . Equal ( t , false , res . Stack [ 0 ] . Value ( ) . ( bool ) )
} ,
} ,
2020-12-14 12:23:39 +00:00
{
name : "unknown contract" ,
params : fmt . Sprintf ( ` ["%s", []] ` , util . Uint160 { } . String ( ) ) ,
fail : true ,
} ,
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
{
name : "not a string" ,
params : ` [42, []] ` ,
fail : true ,
} ,
} ,
2022-04-07 15:13:08 +00:00
"invokecontractverifyhistoric" : {
{
name : "positive, by index" ,
params : fmt . Sprintf ( ` [20,"%s", [], [ { "account":"%s"}]] ` , verifyContractHash , testchain . PrivateKeyByID ( 0 ) . PublicKey ( ) . GetScriptHash ( ) . StringLE ( ) ) ,
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
assert . Nil ( t , res . Script ) // empty witness invocation script (pushes args of `verify` on stack, but this `verify` don't have args)
assert . Equal ( t , "HALT" , res . State )
assert . NotEqual ( t , 0 , res . GasConsumed )
assert . Equal ( t , true , res . Stack [ 0 ] . Value ( ) . ( bool ) , fmt . Sprintf ( "check address in verification_contract.go: expected %s" , testchain . PrivateKeyByID ( 0 ) . Address ( ) ) )
} ,
} ,
{
name : "positive, by stateroot" ,
params : fmt . Sprintf ( ` [" ` + block20StateRootLE + ` ","%s", [], [ { "account":"%s"}]] ` , verifyContractHash , testchain . PrivateKeyByID ( 0 ) . PublicKey ( ) . GetScriptHash ( ) . StringLE ( ) ) ,
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
assert . Nil ( t , res . Script ) // empty witness invocation script (pushes args of `verify` on stack, but this `verify` don't have args)
assert . Equal ( t , "HALT" , res . State )
assert . NotEqual ( t , 0 , res . GasConsumed )
assert . Equal ( t , true , res . Stack [ 0 ] . Value ( ) . ( bool ) , fmt . Sprintf ( "check address in verification_contract.go: expected %s" , testchain . PrivateKeyByID ( 0 ) . Address ( ) ) )
} ,
} ,
{
name : "positive, no signers" ,
params : fmt . Sprintf ( ` [20,"%s", []] ` , verifyContractHash ) ,
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
assert . Nil ( t , res . Script )
assert . Equal ( t , "HALT" , res . State , res . FaultException )
assert . NotEqual ( t , 0 , res . GasConsumed )
assert . Equal ( t , false , res . Stack [ 0 ] . Value ( ) . ( bool ) )
} ,
} ,
{
name : "positive, no arguments" ,
params : fmt . Sprintf ( ` [20,"%s"] ` , verifyContractHash ) ,
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
assert . Nil ( t , res . Script )
assert . Equal ( t , "HALT" , res . State , res . FaultException )
assert . NotEqual ( t , 0 , res . GasConsumed )
assert . Equal ( t , false , res . Stack [ 0 ] . Value ( ) . ( bool ) )
} ,
} ,
{
name : "positive, with signers and scripts" ,
params : fmt . Sprintf ( ` [20,"%s", [], [ { "account":"%s", "invocation":"MQo=", "verification": ""}]] ` , verifyContractHash , testchain . PrivateKeyByID ( 0 ) . PublicKey ( ) . GetScriptHash ( ) . StringLE ( ) ) ,
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
assert . Nil ( t , res . Script )
assert . Equal ( t , "HALT" , res . State )
assert . NotEqual ( t , 0 , res . GasConsumed )
assert . Equal ( t , true , res . Stack [ 0 ] . Value ( ) . ( bool ) )
} ,
} ,
{
name : "positive, with arguments, result=true" ,
params : fmt . Sprintf ( ` [20,"%s", [ { "type": "String", "value": "good_string"}, { "type": "Integer", "value": "4"}, { "type":"Boolean", "value": false}]] ` , verifyWithArgsContractHash ) ,
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
expectedInvScript := io . NewBufBinWriter ( )
emit . Int ( expectedInvScript . BinWriter , 0 )
emit . Int ( expectedInvScript . BinWriter , int64 ( 4 ) )
emit . String ( expectedInvScript . BinWriter , "good_string" )
require . NoError ( t , expectedInvScript . Err )
assert . Equal ( t , expectedInvScript . Bytes ( ) , res . Script ) // witness invocation script (pushes args of `verify` on stack)
assert . Equal ( t , "HALT" , res . State , res . FaultException )
assert . NotEqual ( t , 0 , res . GasConsumed )
assert . Equal ( t , true , res . Stack [ 0 ] . Value ( ) . ( bool ) )
} ,
} ,
{
name : "positive, with arguments, result=false" ,
params : fmt . Sprintf ( ` [20, "%s", [ { "type": "String", "value": "invalid_string"}, { "type": "Integer", "value": "4"}, { "type":"Boolean", "value": false}]] ` , verifyWithArgsContractHash ) ,
result : func ( e * executor ) interface { } { return & result . Invoke { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . Invoke )
require . True ( t , ok )
expectedInvScript := io . NewBufBinWriter ( )
emit . Int ( expectedInvScript . BinWriter , 0 )
emit . Int ( expectedInvScript . BinWriter , int64 ( 4 ) )
emit . String ( expectedInvScript . BinWriter , "invalid_string" )
require . NoError ( t , expectedInvScript . Err )
assert . Equal ( t , expectedInvScript . Bytes ( ) , res . Script )
assert . Equal ( t , "HALT" , res . State , res . FaultException )
assert . NotEqual ( t , 0 , res . GasConsumed )
assert . Equal ( t , false , res . Stack [ 0 ] . Value ( ) . ( bool ) )
} ,
} ,
{
name : "unknown contract" ,
params : fmt . Sprintf ( ` [20, "%s", []] ` , util . Uint160 { } . String ( ) ) ,
fail : true ,
} ,
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
{
name : "no args" ,
params : ` [20] ` ,
fail : true ,
} ,
{
name : "not a string" ,
params : ` [20,42, []] ` ,
fail : true ,
} ,
} ,
2019-11-21 16:41:28 +00:00
"sendrawtransaction" : {
{
name : "positive" ,
2022-06-15 18:23:29 +00:00
params : ` ["ABwAAACWP5gAAAAAAEDaEgAAAAAAFwAAAAHunqIsJ+NL0BSPxBCOCPdOj1BIsoAAXgsDAOh2SBcAAAAMFBEmW7QXJQBBvgTo+iQOOPV8HlabDBTunqIsJ+NL0BSPxBCOCPdOj1BIshTAHwwIdHJhbnNmZXIMFPVj6kC8KD1NDgXEjqMFs/Kgc0DvQWJ9W1IBQgxAEh2U53FB2sU+eeLwTAUqMM5518nsDGil4Oi5IoBiMM7hvl6lKGoYIEaVkf7cS6x4MX1RmSHcoOabKFTyuEXI3SgMIQKzYiv0AXvf4xfFiu1fTHU/IGt9uJYEb6fXdLvEv3+NwkFW57Mn"] ` ,
2020-07-21 07:31:45 +00:00
result : func ( e * executor ) interface { } { return & result . RelayResult { } } ,
check : func ( t * testing . T , e * executor , inv interface { } ) {
res , ok := inv . ( * result . RelayResult )
require . True ( t , ok )
2022-06-15 18:23:29 +00:00
expectedHash := "e4418a8bdad8cdf401aabb277c7bec279d0b0113812c09607039c4ad87204d90"
2021-05-11 13:32:09 +00:00
assert . Equal ( t , expectedHash , res . Hash . StringLE ( ) )
2019-11-21 16:41:28 +00:00
} ,
} ,
{
name : "negative" ,
2020-11-12 11:05:20 +00:00
params : ` ["AAoAAAAxboUQOQGdOd/Cw31sP+4Z/VgJhwAAAAAAAAAA8q0FAAAAAACwBAAAAAExboUQOQGdOd/Cw31sP+4Z/VgJhwFdAwDodkgXAAAADBQgcoJ0r6/Db0OgcdMoz6PmKdnLsAwUMW6FEDkBnTnfwsN9bD/uGf1YCYcTwAwIdHJhbnNmZXIMFIl3INjNdvTwCr+jfA7diJwgj96bQWJ9W1I4AUIMQN+VMUEnEWlCHOurXSegFj4pTXx/LQUltEmHRTRIFP09bFxZHJsXI9BdQoVvQJrbCEz2esySHPr8YpEzpeteen4pDCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcILQQqQav8="] ` ,
2019-11-21 16:41:28 +00:00
fail : true ,
} ,
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
{
name : "invalid string" ,
2020-11-12 11:05:20 +00:00
params : ` ["notabase64%"] ` ,
2019-11-21 16:41:28 +00:00
fail : true ,
} ,
{
name : "invalid tx" ,
2020-11-12 11:05:20 +00:00
params : ` ["AnTXkgcmF3IGNvbnRyYWNw=="] ` ,
2019-11-21 16:41:28 +00:00
fail : true ,
} ,
} ,
2020-03-02 17:01:32 +00:00
"submitblock" : {
{
2020-11-12 11:05:20 +00:00
name : "invalid base64" ,
params : ` ["%%%"] ` ,
2020-03-02 17:01:32 +00:00
fail : true ,
} ,
{
name : "invalid block bytes" ,
2020-11-12 11:05:20 +00:00
params : ` ["AAAAACc="] ` ,
2020-03-02 17:01:32 +00:00
fail : true ,
} ,
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
} ,
2020-09-28 11:58:04 +00:00
"submitoracleresponse" : {
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
} ,
2021-02-09 09:05:45 +00:00
"submitnotaryrequest" : {
{
name : "no params" ,
params : ` [] ` ,
fail : true ,
} ,
} ,
2019-11-21 16:41:28 +00:00
"validateaddress" : {
{
name : "positive" ,
2020-06-16 10:47:29 +00:00
params : ` ["Nbb1qkwcwNSBs9pAnrVVrnFbWnbWBk91U2"] ` ,
2020-02-21 12:10:59 +00:00
result : func ( * executor ) interface { } { return & result . ValidateAddress { } } ,
check : func ( t * testing . T , e * executor , va interface { } ) {
res , ok := va . ( * result . ValidateAddress )
2019-11-21 16:41:28 +00:00
require . True ( t , ok )
2020-06-16 10:47:29 +00:00
assert . Equal ( t , "Nbb1qkwcwNSBs9pAnrVVrnFbWnbWBk91U2" , res . Address )
2020-02-21 12:10:59 +00:00
assert . True ( t , res . IsValid )
2019-11-21 16:41:28 +00:00
} ,
} ,
{
name : "negative" ,
params : "[1]" ,
result : func ( * executor ) interface { } {
2020-02-21 12:10:59 +00:00
return & result . ValidateAddress {
Address : float64 ( 1 ) ,
IsValid : false ,
2019-11-21 16:41:28 +00:00
}
} ,
} ,
} ,
}
2019-01-22 12:14:52 +00:00
2019-11-21 16:41:28 +00:00
func TestRPC ( t * testing . T ) {
2020-04-29 12:25:58 +00:00
t . Run ( "http" , func ( t * testing . T ) {
testRPCProtocol ( t , doRPCCallOverHTTP )
} )
t . Run ( "websocket" , func ( t * testing . T ) {
testRPCProtocol ( t , doRPCCallOverWS )
} )
}
2020-09-28 11:58:04 +00:00
func TestSubmitOracle ( t * testing . T ) {
2022-06-15 18:23:29 +00:00
chain , rpcSrv , httpSrv := initClearServerWithServices ( t , true , false , false )
2020-09-28 11:58:04 +00:00
defer chain . Close ( )
2022-04-22 07:49:06 +00:00
defer rpcSrv . Shutdown ( )
2020-09-28 11:58:04 +00:00
rpc := ` { "jsonrpc": "2.0", "id": 1, "method": "submitoracleresponse", "params": %s} `
runCase := func ( t * testing . T , fail bool , params ... string ) func ( t * testing . T ) {
return func ( t * testing . T ) {
ps := ` [ ` + strings . Join ( params , "," ) + ` ] `
req := fmt . Sprintf ( rpc , ps )
body := doRPCCallOverHTTP ( req , httpSrv . URL , t )
checkErrGetResult ( t , body , fail )
}
}
t . Run ( "MissingKey" , runCase ( t , true ) )
t . Run ( "InvalidKey" , runCase ( t , true , ` "1234" ` ) )
priv , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
pubStr := ` " ` + base64 . StdEncoding . EncodeToString ( priv . PublicKey ( ) . Bytes ( ) ) + ` " `
t . Run ( "InvalidReqID" , runCase ( t , true , pubStr , ` "notanumber" ` ) )
t . Run ( "InvalidTxSignature" , runCase ( t , true , pubStr , ` 1 ` , ` "qwerty" ` ) )
txSig := priv . Sign ( [ ] byte { 1 , 2 , 3 } )
txSigStr := ` " ` + base64 . StdEncoding . EncodeToString ( txSig ) + ` " `
t . Run ( "MissingMsgSignature" , runCase ( t , true , pubStr , ` 1 ` , txSigStr ) )
t . Run ( "InvalidMsgSignature" , runCase ( t , true , pubStr , ` 1 ` , txSigStr , ` "0123" ` ) )
msg := rpc2 . GetMessage ( priv . PublicKey ( ) . Bytes ( ) , 1 , txSig )
msgSigStr := ` " ` + base64 . StdEncoding . EncodeToString ( priv . Sign ( msg ) ) + ` " `
t . Run ( "Valid" , runCase ( t , false , pubStr , ` 1 ` , txSigStr , msgSigStr ) )
}
2021-02-09 09:05:45 +00:00
func TestSubmitNotaryRequest ( t * testing . T ) {
rpc := ` { "jsonrpc": "2.0", "id": 1, "method": "submitnotaryrequest", "params": %s} `
t . Run ( "disabled P2PSigExtensions" , func ( t * testing . T ) {
2022-06-15 18:23:29 +00:00
chain , rpcSrv , httpSrv := initClearServerWithServices ( t , false , false , false )
2021-02-09 09:05:45 +00:00
defer chain . Close ( )
2022-04-22 07:49:06 +00:00
defer rpcSrv . Shutdown ( )
2021-02-09 09:05:45 +00:00
req := fmt . Sprintf ( rpc , "[]" )
body := doRPCCallOverHTTP ( req , httpSrv . URL , t )
checkErrGetResult ( t , body , true )
} )
2022-06-15 18:23:29 +00:00
chain , rpcSrv , httpSrv := initServerWithInMemoryChainAndServices ( t , false , true , false )
2021-02-09 09:05:45 +00:00
defer chain . Close ( )
2022-04-22 07:49:06 +00:00
defer rpcSrv . Shutdown ( )
2021-02-09 09:05:45 +00:00
runCase := func ( t * testing . T , fail bool , params ... string ) func ( t * testing . T ) {
return func ( t * testing . T ) {
ps := ` [ ` + strings . Join ( params , "," ) + ` ] `
req := fmt . Sprintf ( rpc , ps )
body := doRPCCallOverHTTP ( req , httpSrv . URL , t )
checkErrGetResult ( t , body , fail )
}
}
t . Run ( "missing request" , runCase ( t , true ) )
t . Run ( "not a base64" , runCase ( t , true , ` "not-a-base64$" ` ) )
t . Run ( "invalid request bytes" , runCase ( t , true , ` "not-a-request" ` ) )
t . Run ( "invalid request" , func ( t * testing . T ) {
mainTx := & transaction . Transaction {
Attributes : [ ] transaction . Attribute { { Type : transaction . NotaryAssistedT , Value : & transaction . NotaryAssisted { NKeys : 1 } } } ,
Script : [ ] byte { byte ( opcode . RET ) } ,
ValidUntilBlock : 123 ,
Signers : [ ] transaction . Signer { { Account : util . Uint160 { 1 , 5 , 9 } } } ,
Scripts : [ ] transaction . Witness { {
InvocationScript : [ ] byte { 1 , 4 , 7 } ,
VerificationScript : [ ] byte { 3 , 6 , 9 } ,
} } ,
}
fallbackTx := & transaction . Transaction {
Script : [ ] byte { byte ( opcode . RET ) } ,
ValidUntilBlock : 123 ,
Attributes : [ ] transaction . Attribute {
{ Type : transaction . NotValidBeforeT , Value : & transaction . NotValidBefore { Height : 123 } } ,
{ Type : transaction . ConflictsT , Value : & transaction . Conflicts { Hash : mainTx . Hash ( ) } } ,
{ Type : transaction . NotaryAssistedT , Value : & transaction . NotaryAssisted { NKeys : 0 } } ,
} ,
Signers : [ ] transaction . Signer { { Account : util . Uint160 { 1 , 4 , 7 } } , { Account : util . Uint160 { 9 , 8 , 7 } } } ,
Scripts : [ ] transaction . Witness {
2022-10-05 07:45:52 +00:00
{ InvocationScript : append ( [ ] byte { byte ( opcode . PUSHDATA1 ) , keys . SignatureLen } , make ( [ ] byte , keys . SignatureLen ) ... ) , VerificationScript : make ( [ ] byte , 0 ) } ,
2021-02-09 09:05:45 +00:00
{ InvocationScript : [ ] byte { 1 , 2 , 3 } , VerificationScript : [ ] byte { 1 , 2 , 3 } } } ,
}
p := & payload . P2PNotaryRequest {
MainTransaction : mainTx ,
FallbackTransaction : fallbackTx ,
Witness : transaction . Witness {
InvocationScript : [ ] byte { 1 , 2 , 3 } ,
VerificationScript : [ ] byte { 7 , 8 , 9 } ,
} ,
}
bytes , err := p . Bytes ( )
require . NoError ( t , err )
str := fmt . Sprintf ( ` "%s" ` , base64 . StdEncoding . EncodeToString ( bytes ) )
runCase ( t , true , str ) ( t )
} )
t . Run ( "valid request" , func ( t * testing . T ) {
sender := testchain . PrivateKeyByID ( 0 ) // owner of the deposit in testchain
2021-05-28 11:55:06 +00:00
p := createValidNotaryRequest ( chain , sender , 1 )
2021-02-09 09:05:45 +00:00
bytes , err := p . Bytes ( )
require . NoError ( t , err )
str := fmt . Sprintf ( ` "%s" ` , base64 . StdEncoding . EncodeToString ( bytes ) )
runCase ( t , false , str ) ( t )
} )
}
2021-05-28 11:55:06 +00:00
// createValidNotaryRequest creates and signs P2PNotaryRequest payload which can
// pass verification.
func createValidNotaryRequest ( chain * core . Blockchain , sender * keys . PrivateKey , nonce uint32 ) * payload . P2PNotaryRequest {
h := chain . BlockHeight ( )
mainTx := & transaction . Transaction {
Nonce : nonce ,
Attributes : [ ] transaction . Attribute { { Type : transaction . NotaryAssistedT , Value : & transaction . NotaryAssisted { NKeys : 1 } } } ,
Script : [ ] byte { byte ( opcode . RET ) } ,
ValidUntilBlock : h + 100 ,
Signers : [ ] transaction . Signer { { Account : sender . GetScriptHash ( ) } } ,
Scripts : [ ] transaction . Witness { {
InvocationScript : [ ] byte { 1 , 4 , 7 } ,
VerificationScript : [ ] byte { 3 , 6 , 9 } ,
} } ,
}
fallbackTx := & transaction . Transaction {
Script : [ ] byte { byte ( opcode . RET ) } ,
ValidUntilBlock : h + 100 ,
Attributes : [ ] transaction . Attribute {
{ Type : transaction . NotValidBeforeT , Value : & transaction . NotValidBefore { Height : h + 50 } } ,
{ Type : transaction . ConflictsT , Value : & transaction . Conflicts { Hash : mainTx . Hash ( ) } } ,
{ Type : transaction . NotaryAssistedT , Value : & transaction . NotaryAssisted { NKeys : 0 } } ,
} ,
Signers : [ ] transaction . Signer { { Account : chain . GetNotaryContractScriptHash ( ) } , { Account : sender . GetScriptHash ( ) } } ,
Scripts : [ ] transaction . Witness {
2022-10-05 07:45:52 +00:00
{ InvocationScript : append ( [ ] byte { byte ( opcode . PUSHDATA1 ) , keys . SignatureLen } , make ( [ ] byte , keys . SignatureLen ) ... ) , VerificationScript : [ ] byte { } } ,
2021-05-28 11:55:06 +00:00
} ,
NetworkFee : 2_0000_0000 ,
}
fallbackTx . Scripts = append ( fallbackTx . Scripts , transaction . Witness {
2022-10-05 07:45:52 +00:00
InvocationScript : append ( [ ] byte { byte ( opcode . PUSHDATA1 ) , keys . SignatureLen } , sender . SignHashable ( uint32 ( testchain . Network ( ) ) , fallbackTx ) ... ) ,
2021-05-28 11:55:06 +00:00
VerificationScript : sender . PublicKey ( ) . GetVerificationScript ( ) ,
} )
p := & payload . P2PNotaryRequest {
MainTransaction : mainTx ,
FallbackTransaction : fallbackTx ,
}
p . Witness = transaction . Witness {
2022-10-05 07:45:52 +00:00
InvocationScript : append ( [ ] byte { byte ( opcode . PUSHDATA1 ) , keys . SignatureLen } , sender . SignHashable ( uint32 ( testchain . Network ( ) ) , p ) ... ) ,
2021-05-28 11:55:06 +00:00
VerificationScript : sender . PublicKey ( ) . GetVerificationScript ( ) ,
}
return p
}
2020-04-29 12:25:58 +00:00
// testRPCProtocol runs a full set of tests using given callback to make actual
// calls. Some tests change the chain state, thus we reinitialize the chain from
// scratch here.
func testRPCProtocol ( t * testing . T , doRPCCall func ( string , string , * testing . T ) [ ] byte ) {
2020-05-09 20:59:21 +00:00
chain , rpcSrv , httpSrv := initServerWithInMemoryChain ( t )
2019-01-22 12:14:52 +00:00
2020-01-10 08:47:55 +00:00
defer chain . Close ( )
2022-04-22 07:49:06 +00:00
defer rpcSrv . Shutdown ( )
2020-01-10 08:47:55 +00:00
2020-04-29 12:14:56 +00:00
e := & executor { chain : chain , httpSrv : httpSrv }
2020-10-26 17:22:20 +00:00
t . Run ( "single request" , func ( t * testing . T ) {
for method , cases := range rpcTestCases {
t . Run ( method , func ( t * testing . T ) {
rpc := ` { "jsonrpc": "2.0", "id": 1, "method": "%s", "params": %s} `
2019-01-22 12:14:52 +00:00
2020-10-26 17:22:20 +00:00
for _ , tc := range cases {
t . Run ( tc . name , func ( t * testing . T ) {
body := doRPCCall ( fmt . Sprintf ( rpc , method , tc . params ) , httpSrv . URL , t )
result := checkErrGetResult ( t , body , tc . fail )
if tc . fail {
return
}
expected , res := tc . getResultPair ( e )
err := json . Unmarshal ( result , res )
require . NoErrorf ( t , err , "could not parse response: %s" , result )
if tc . check == nil {
assert . Equal ( t , expected , res )
} else {
tc . check ( t , e , res )
}
} )
}
} )
}
} )
t . Run ( "batch with single request" , func ( t * testing . T ) {
for method , cases := range rpcTestCases {
if method == "sendrawtransaction" {
continue // cannot send the same transaction twice
}
t . Run ( method , func ( t * testing . T ) {
rpc := ` [ { "jsonrpc": "2.0", "id": 1, "method": "%s", "params": %s}] `
for _ , tc := range cases {
t . Run ( tc . name , func ( t * testing . T ) {
body := doRPCCall ( fmt . Sprintf ( rpc , method , tc . params ) , httpSrv . URL , t )
result := checkErrGetBatchResult ( t , body , tc . fail )
if tc . fail {
return
}
expected , res := tc . getResultPair ( e )
err := json . Unmarshal ( result , res )
require . NoErrorf ( t , err , "could not parse response: %s" , result )
if tc . check == nil {
assert . Equal ( t , expected , res )
} else {
tc . check ( t , e , res )
}
} )
}
} )
}
} )
t . Run ( "batch with multiple requests" , func ( t * testing . T ) {
for method , cases := range rpcTestCases {
if method == "sendrawtransaction" {
continue // cannot send the same transaction twice
}
t . Run ( method , func ( t * testing . T ) {
rpc := ` { "jsonrpc": "2.0", "id": %d, "method": "%s", "params": %s}, `
var resultRPC string
for i , tc := range cases {
resultRPC += fmt . Sprintf ( rpc , i , method , tc . params )
}
resultRPC = ` [ ` + resultRPC [ : len ( resultRPC ) - 1 ] + ` ] `
body := doRPCCall ( resultRPC , httpSrv . URL , t )
2022-07-22 16:09:29 +00:00
var responses [ ] neorpc . Response
2020-10-26 17:22:20 +00:00
err := json . Unmarshal ( body , & responses )
require . Nil ( t , err )
for i , tc := range cases {
2022-07-22 16:09:29 +00:00
var resp neorpc . Response
2020-10-26 17:22:20 +00:00
for _ , r := range responses {
if bytes . Equal ( r . ID , [ ] byte ( strconv . Itoa ( i ) ) ) {
resp = r
break
}
}
if tc . fail {
require . NotNil ( t , resp . Error )
assert . NotEqual ( t , 0 , resp . Error . Code )
assert . NotEqual ( t , "" , resp . Error . Message )
} else {
assert . Nil ( t , resp . Error )
}
2019-11-21 16:41:28 +00:00
if tc . fail {
return
}
expected , res := tc . getResultPair ( e )
2020-10-26 17:22:20 +00:00
err := json . Unmarshal ( resp . Result , res )
require . NoErrorf ( t , err , "could not parse response: %s" , resp . Result )
2019-02-20 17:39:32 +00:00
2019-11-21 16:41:28 +00:00
if tc . check == nil {
assert . Equal ( t , expected , res )
} else {
tc . check ( t , e , res )
}
2020-10-26 17:22:20 +00:00
}
} )
}
} )
2019-11-15 19:04:10 +00:00
2020-06-18 20:09:24 +00:00
t . Run ( "getapplicationlog for block" , func ( t * testing . T ) {
rpc := ` { "jsonrpc": "2.0", "id": 1, "method": "getapplicationlog", "params": ["%s"]} `
body := doRPCCall ( fmt . Sprintf ( rpc , e . chain . GetHeaderHash ( 1 ) . StringLE ( ) ) , httpSrv . URL , t )
data := checkErrGetResult ( t , body , false )
2020-11-11 15:43:28 +00:00
var res result . ApplicationLog
2020-06-18 20:09:24 +00:00
require . NoError ( t , json . Unmarshal ( data , & res ) )
2020-11-11 15:43:28 +00:00
require . Equal ( t , 2 , len ( res . Executions ) )
require . Equal ( t , trigger . OnPersist , res . Executions [ 0 ] . Trigger )
2022-07-08 14:28:29 +00:00
require . Equal ( t , vmstate . Halt , res . Executions [ 0 ] . VMState )
2020-11-11 15:43:28 +00:00
require . Equal ( t , trigger . PostPersist , res . Executions [ 1 ] . Trigger )
2022-07-08 14:28:29 +00:00
require . Equal ( t , vmstate . Halt , res . Executions [ 1 ] . VMState )
2020-06-18 20:09:24 +00:00
} )
2020-04-23 13:32:53 +00:00
t . Run ( "submit" , func ( t * testing . T ) {
rpc := ` { "jsonrpc": "2.0", "id": 1, "method": "submitblock", "params": ["%s"]} `
2020-05-06 10:11:28 +00:00
t . Run ( "invalid signature" , func ( t * testing . T ) {
2020-08-20 15:47:14 +00:00
s := testchain . NewBlock ( t , chain , 1 , 0 )
2020-05-06 10:11:28 +00:00
s . Script . VerificationScript [ 8 ] ^ = 0xff
2020-05-04 13:53:36 +00:00
body := doRPCCall ( fmt . Sprintf ( rpc , encodeBlock ( t , s ) ) , httpSrv . URL , t )
2020-04-23 13:32:53 +00:00
checkErrGetResult ( t , body , true )
} )
2020-05-08 17:54:24 +00:00
priv0 := testchain . PrivateKeyByID ( 0 )
2020-12-04 09:40:22 +00:00
acc0 := wallet . NewAccountFromPrivateKey ( priv0 )
2020-05-08 17:54:24 +00:00
addNetworkFee := func ( tx * transaction . Transaction ) {
size := io . GetVarSize ( tx )
2020-12-11 12:22:49 +00:00
netFee , sizeDelta := fee . Calculate ( chain . GetBaseExecFee ( ) , acc0 . Contract . Script )
2020-05-08 17:54:24 +00:00
tx . NetworkFee += netFee
size += sizeDelta
2020-06-23 14:15:35 +00:00
tx . NetworkFee += int64 ( size ) * chain . FeePerByte ( )
2020-05-08 17:54:24 +00:00
}
2020-04-23 13:32:53 +00:00
newTx := func ( ) * transaction . Transaction {
height := chain . BlockHeight ( )
2021-03-25 16:18:01 +00:00
tx := transaction . New ( [ ] byte { byte ( opcode . PUSH1 ) } , 0 )
2020-04-22 17:42:38 +00:00
tx . Nonce = height + 1
2020-04-23 13:32:53 +00:00
tx . ValidUntilBlock = height + 10
2020-07-29 16:57:38 +00:00
tx . Signers = [ ] transaction . Signer { { Account : acc0 . PrivateKey ( ) . GetScriptHash ( ) } }
2020-05-08 17:54:24 +00:00
addNetworkFee ( tx )
2021-03-25 16:18:01 +00:00
require . NoError ( t , acc0 . SignTx ( testchain . Network ( ) , tx ) )
2020-04-23 13:32:53 +00:00
return tx
}
t . Run ( "invalid height" , func ( t * testing . T ) {
2020-08-20 15:47:14 +00:00
b := testchain . NewBlock ( t , chain , 2 , 0 , newTx ( ) )
2020-04-29 12:14:56 +00:00
body := doRPCCall ( fmt . Sprintf ( rpc , encodeBlock ( t , b ) ) , httpSrv . URL , t )
2020-04-23 13:32:53 +00:00
checkErrGetResult ( t , body , true )
} )
t . Run ( "positive" , func ( t * testing . T ) {
2020-08-20 15:47:14 +00:00
b := testchain . NewBlock ( t , chain , 1 , 0 , newTx ( ) )
2020-04-29 12:14:56 +00:00
body := doRPCCall ( fmt . Sprintf ( rpc , encodeBlock ( t , b ) ) , httpSrv . URL , t )
2020-04-23 13:32:53 +00:00
data := checkErrGetResult ( t , body , false )
2020-07-21 07:41:18 +00:00
var res = new ( result . RelayResult )
require . NoError ( t , json . Unmarshal ( data , res ) )
require . Equal ( t , b . Hash ( ) , res . Hash )
2020-04-23 13:32:53 +00:00
} )
} )
2020-06-05 08:51:39 +00:00
t . Run ( "getproof" , func ( t * testing . T ) {
2021-01-29 14:33:24 +00:00
r , err := chain . GetStateModule ( ) . GetStateRoot ( 3 )
2020-06-05 08:51:39 +00:00
require . NoError ( t , err )
2021-03-30 10:08:13 +00:00
rpc := fmt . Sprintf ( ` { "jsonrpc": "2.0", "id": 1, "method": "getproof", "params": ["%s", "%s", "%s"]} ` ,
r . Root . StringLE ( ) , testContractHash , base64 . StdEncoding . EncodeToString ( [ ] byte ( "testkey" ) ) )
2020-06-05 08:51:39 +00:00
body := doRPCCall ( rpc , httpSrv . URL , t )
rawRes := checkErrGetResult ( t , body , false )
2021-03-30 10:08:13 +00:00
res := new ( result . ProofWithKey )
2020-06-05 08:51:39 +00:00
require . NoError ( t , json . Unmarshal ( rawRes , res ) )
h , _ := util . Uint160DecodeStringLE ( testContractHash )
skey := makeStorageKey ( chain . GetContractState ( h ) . ID , [ ] byte ( "testkey" ) )
2021-03-30 10:08:13 +00:00
require . Equal ( t , skey , res . Key )
require . True ( t , len ( res . Proof ) > 0 )
2020-06-05 08:51:39 +00:00
rpc = fmt . Sprintf ( ` { "jsonrpc": "2.0", "id": 1, "method": "verifyproof", "params": ["%s", "%s"]} ` ,
2021-03-30 10:08:13 +00:00
r . Root . StringLE ( ) , res . String ( ) )
2020-06-05 08:51:39 +00:00
body = doRPCCall ( rpc , httpSrv . URL , t )
rawRes = checkErrGetResult ( t , body , false )
vp := new ( result . VerifyProof )
require . NoError ( t , json . Unmarshal ( rawRes , vp ) )
require . Equal ( t , [ ] byte ( "testvalue" ) , vp . Value )
} )
2020-06-03 15:09:36 +00:00
t . Run ( "getstateroot" , func ( t * testing . T ) {
testRoot := func ( t * testing . T , p string ) {
rpc := fmt . Sprintf ( ` { "jsonrpc": "2.0", "id": 1, "method": "getstateroot", "params": [%s]} ` , p )
body := doRPCCall ( rpc , httpSrv . URL , t )
rawRes := checkErrGetResult ( t , body , false )
2021-03-25 19:11:55 +00:00
res := & state . MPTRoot { }
2020-06-03 15:09:36 +00:00
require . NoError ( t , json . Unmarshal ( rawRes , res ) )
require . NotEqual ( t , util . Uint256 { } , res . Root ) // be sure this test uses valid height
2021-01-29 14:33:24 +00:00
expected , err := e . chain . GetStateModule ( ) . GetStateRoot ( 5 )
2020-06-03 15:09:36 +00:00
require . NoError ( t , err )
require . Equal ( t , expected , res )
}
t . Run ( "ByHeight" , func ( t * testing . T ) { testRoot ( t , strconv . FormatInt ( 5 , 10 ) ) } )
t . Run ( "ByHash" , func ( t * testing . T ) { testRoot ( t , ` " ` + chain . GetHeaderHash ( 5 ) . StringLE ( ) + ` " ` ) } )
} )
2021-10-07 09:03:37 +00:00
t . Run ( "getstate" , func ( t * testing . T ) {
testGetState := func ( t * testing . T , p string , expected string ) {
rpc := fmt . Sprintf ( ` { "jsonrpc": "2.0", "id": 1, "method": "getstate", "params": [%s]} ` , p )
body := doRPCCall ( rpc , httpSrv . URL , t )
rawRes := checkErrGetResult ( t , body , false )
var actual string
require . NoError ( t , json . Unmarshal ( rawRes , & actual ) )
require . Equal ( t , expected , actual )
}
t . Run ( "good: historical state" , func ( t * testing . T ) {
root , err := e . chain . GetStateModule ( ) . GetStateRoot ( 4 )
require . NoError ( t , err )
// `testkey`-`testvalue` pair was put to the contract storage at block #3
params := fmt . Sprintf ( ` "%s", "%s", "%s" ` , root . Root . StringLE ( ) , testContractHash , base64 . StdEncoding . EncodeToString ( [ ] byte ( "testkey" ) ) )
testGetState ( t , params , base64 . StdEncoding . EncodeToString ( [ ] byte ( "testvalue" ) ) )
} )
t . Run ( "good: fresh state" , func ( t * testing . T ) {
root , err := e . chain . GetStateModule ( ) . GetStateRoot ( 16 )
require . NoError ( t , err )
// `testkey`-`newtestvalue` pair was put to the contract storage at block #16
params := fmt . Sprintf ( ` "%s", "%s", "%s" ` , root . Root . StringLE ( ) , testContractHash , base64 . StdEncoding . EncodeToString ( [ ] byte ( "testkey" ) ) )
testGetState ( t , params , base64 . StdEncoding . EncodeToString ( [ ] byte ( "newtestvalue" ) ) )
} )
} )
2021-10-07 13:56:27 +00:00
t . Run ( "findstates" , func ( t * testing . T ) {
testFindStates := func ( t * testing . T , p string , root util . Uint256 , expected result . FindStates ) {
rpc := fmt . Sprintf ( ` { "jsonrpc": "2.0", "id": 1, "method": "findstates", "params": [%s]} ` , p )
body := doRPCCall ( rpc , httpSrv . URL , t )
rawRes := checkErrGetResult ( t , body , false )
var actual result . FindStates
require . NoError ( t , json . Unmarshal ( rawRes , & actual ) )
require . Equal ( t , expected . Results , actual . Results )
checkProof := func ( t * testing . T , proof * result . ProofWithKey , value [ ] byte ) {
rpc = fmt . Sprintf ( ` { "jsonrpc": "2.0", "id": 1, "method": "verifyproof", "params": ["%s", "%s"]} ` ,
root . StringLE ( ) , proof . String ( ) )
body = doRPCCall ( rpc , httpSrv . URL , t )
rawRes = checkErrGetResult ( t , body , false )
vp := new ( result . VerifyProof )
require . NoError ( t , json . Unmarshal ( rawRes , vp ) )
require . Equal ( t , value , vp . Value )
}
checkProof ( t , actual . FirstProof , actual . Results [ 0 ] . Value )
if len ( actual . Results ) > 1 {
checkProof ( t , actual . LastProof , actual . Results [ len ( actual . Results ) - 1 ] . Value )
}
require . Equal ( t , expected . Truncated , actual . Truncated )
}
t . Run ( "good: no prefix, no limit" , func ( t * testing . T ) {
// pairs for this test where put to the contract storage at block #16
root , err := e . chain . GetStateModule ( ) . GetStateRoot ( 16 )
require . NoError ( t , err )
params := fmt . Sprintf ( ` "%s", "%s", "%s" ` , root . Root . StringLE ( ) , testContractHash , base64 . StdEncoding . EncodeToString ( [ ] byte ( "aa" ) ) )
testFindStates ( t , params , root . Root , result . FindStates {
Results : [ ] result . KeyValue {
{ Key : [ ] byte ( "aa10" ) , Value : [ ] byte ( "v2" ) } ,
{ Key : [ ] byte ( "aa50" ) , Value : [ ] byte ( "v3" ) } ,
{ Key : [ ] byte ( "aa" ) , Value : [ ] byte ( "v1" ) } ,
} ,
Truncated : false ,
} )
} )
2021-10-13 08:38:53 +00:00
t . Run ( "good: empty prefix, no limit" , func ( t * testing . T ) {
// empty prefix should be considered as no prefix specified.
root , err := e . chain . GetStateModule ( ) . GetStateRoot ( 16 )
require . NoError ( t , err )
params := fmt . Sprintf ( ` "%s", "%s", "%s", "" ` , root . Root . StringLE ( ) , testContractHash , base64 . StdEncoding . EncodeToString ( [ ] byte ( "aa" ) ) )
testFindStates ( t , params , root . Root , result . FindStates {
Results : [ ] result . KeyValue {
{ Key : [ ] byte ( "aa10" ) , Value : [ ] byte ( "v2" ) } ,
{ Key : [ ] byte ( "aa50" ) , Value : [ ] byte ( "v3" ) } ,
{ Key : [ ] byte ( "aa" ) , Value : [ ] byte ( "v1" ) } ,
} ,
Truncated : false ,
} )
} )
2021-10-07 13:56:27 +00:00
t . Run ( "good: with prefix, no limit" , func ( t * testing . T ) {
// pairs for this test where put to the contract storage at block #16
root , err := e . chain . GetStateModule ( ) . GetStateRoot ( 16 )
require . NoError ( t , err )
params := fmt . Sprintf ( ` "%s", "%s", "%s", "%s" ` , root . Root . StringLE ( ) , testContractHash , base64 . StdEncoding . EncodeToString ( [ ] byte ( "aa" ) ) , base64 . StdEncoding . EncodeToString ( [ ] byte ( "aa10" ) ) )
testFindStates ( t , params , root . Root , result . FindStates {
Results : [ ] result . KeyValue {
{ Key : [ ] byte ( "aa50" ) , Value : [ ] byte ( "v3" ) } ,
} ,
Truncated : false ,
} )
} )
2021-10-13 08:38:53 +00:00
t . Run ( "good: empty prefix, with limit" , func ( t * testing . T ) {
2021-10-07 13:56:27 +00:00
for limit := 2 ; limit < 5 ; limit ++ {
// pairs for this test where put to the contract storage at block #16
root , err := e . chain . GetStateModule ( ) . GetStateRoot ( 16 )
require . NoError ( t , err )
params := fmt . Sprintf ( ` "%s", "%s", "%s", "", %d ` , root . Root . StringLE ( ) , testContractHash , base64 . StdEncoding . EncodeToString ( [ ] byte ( "aa" ) ) , limit )
expected := result . FindStates {
Results : [ ] result . KeyValue {
{ Key : [ ] byte ( "aa10" ) , Value : [ ] byte ( "v2" ) } ,
{ Key : [ ] byte ( "aa50" ) , Value : [ ] byte ( "v3" ) } ,
} ,
Truncated : limit == 2 ,
}
if limit != 2 {
expected . Results = append ( expected . Results , result . KeyValue { Key : [ ] byte ( "aa" ) , Value : [ ] byte ( "v1" ) } )
}
testFindStates ( t , params , root . Root , expected )
}
} )
t . Run ( "good: with prefix, with limit" , func ( t * testing . T ) {
// pairs for this test where put to the contract storage at block #16
root , err := e . chain . GetStateModule ( ) . GetStateRoot ( 16 )
require . NoError ( t , err )
params := fmt . Sprintf ( ` "%s", "%s", "%s", "%s", %d ` , root . Root . StringLE ( ) , testContractHash , base64 . StdEncoding . EncodeToString ( [ ] byte ( "aa" ) ) , base64 . StdEncoding . EncodeToString ( [ ] byte ( "aa00" ) ) , 1 )
testFindStates ( t , params , root . Root , result . FindStates {
Results : [ ] result . KeyValue {
{ Key : [ ] byte ( "aa10" ) , Value : [ ] byte ( "v2" ) } ,
} ,
Truncated : true ,
} )
} )
} )
2020-04-23 13:32:53 +00:00
2019-09-18 15:21:16 +00:00
t . Run ( "getrawtransaction" , func ( t * testing . T ) {
2020-12-08 15:28:00 +00:00
block , _ := chain . GetBlock ( chain . GetHeaderHash ( 1 ) )
2020-06-05 13:07:04 +00:00
tx := block . Transactions [ 0 ]
rpc := fmt . Sprintf ( ` { "jsonrpc": "2.0", "id": 1, "method": "getrawtransaction", "params": ["%s"]}" ` , tx . Hash ( ) . StringLE ( ) )
2020-04-29 12:14:56 +00:00
body := doRPCCall ( rpc , httpSrv . URL , t )
2020-02-21 12:10:59 +00:00
result := checkErrGetResult ( t , body , false )
var res string
err := json . Unmarshal ( result , & res )
require . NoErrorf ( t , err , "could not parse response: %s" , result )
2020-06-05 13:07:04 +00:00
txBin , err := testserdes . EncodeBinary ( tx )
require . NoError ( t , err )
2020-11-06 14:37:58 +00:00
expected := base64 . StdEncoding . EncodeToString ( txBin )
2020-06-05 13:07:04 +00:00
assert . Equal ( t , expected , res )
2019-09-18 15:21:16 +00:00
} )
2019-01-22 12:14:52 +00:00
2019-11-21 16:41:28 +00:00
t . Run ( "getrawtransaction 2 arguments" , func ( t * testing . T ) {
2020-12-08 15:28:00 +00:00
block , _ := chain . GetBlock ( chain . GetHeaderHash ( 1 ) )
2020-06-05 13:07:04 +00:00
tx := block . Transactions [ 0 ]
rpc := fmt . Sprintf ( ` { "jsonrpc": "2.0", "id": 1, "method": "getrawtransaction", "params": ["%s", 0]}" ` , tx . Hash ( ) . StringLE ( ) )
2020-04-29 12:14:56 +00:00
body := doRPCCall ( rpc , httpSrv . URL , t )
2020-02-21 12:10:59 +00:00
result := checkErrGetResult ( t , body , false )
var res string
err := json . Unmarshal ( result , & res )
require . NoErrorf ( t , err , "could not parse response: %s" , result )
2020-06-05 13:07:04 +00:00
txBin , err := testserdes . EncodeBinary ( tx )
require . NoError ( t , err )
2020-11-06 14:37:58 +00:00
expected := base64 . StdEncoding . EncodeToString ( txBin )
2020-06-05 13:07:04 +00:00
assert . Equal ( t , expected , res )
2019-09-18 15:21:16 +00:00
} )
2020-02-06 12:02:03 +00:00
2020-03-23 14:31:28 +00:00
t . Run ( "getrawtransaction 2 arguments, verbose" , func ( t * testing . T ) {
2020-12-08 15:28:00 +00:00
block , _ := chain . GetBlock ( chain . GetHeaderHash ( 1 ) )
2020-04-22 17:42:38 +00:00
TXHash := block . Transactions [ 0 ] . Hash ( )
2020-09-10 16:28:16 +00:00
_ = block . Transactions [ 0 ] . Size ( )
2020-03-23 14:31:28 +00:00
rpc := fmt . Sprintf ( ` { "jsonrpc": "2.0", "id": 1, "method": "getrawtransaction", "params": ["%s", 1]}" ` , TXHash . StringLE ( ) )
2020-04-29 12:14:56 +00:00
body := doRPCCall ( rpc , httpSrv . URL , t )
2020-03-23 14:31:28 +00:00
txOut := checkErrGetResult ( t , body , false )
2021-03-25 16:18:01 +00:00
actual := result . TransactionOutputRaw { Transaction : transaction . Transaction { } }
2020-03-23 14:31:28 +00:00
err := json . Unmarshal ( txOut , & actual )
require . NoErrorf ( t , err , "could not parse response: %s" , txOut )
2020-06-18 08:47:54 +00:00
assert . Equal ( t , * block . Transactions [ 0 ] , actual . Transaction )
2022-06-15 18:23:29 +00:00
assert . Equal ( t , 23 , actual . Confirmations )
2020-03-23 14:31:28 +00:00
assert . Equal ( t , TXHash , actual . Transaction . Hash ( ) )
} )
2020-04-23 13:02:01 +00:00
t . Run ( "getblockheader_positive" , func ( t * testing . T ) {
rpc := ` { "jsonrpc": "2.0", "id": 1, "method": "getblockheader", "params": %s} `
testHeaderHash := chain . GetHeaderHash ( 1 ) . StringLE ( )
hdr := e . getHeader ( testHeaderHash )
runCase := func ( t * testing . T , rpc string , expected , actual interface { } ) {
2020-04-29 12:14:56 +00:00
body := doRPCCall ( rpc , httpSrv . URL , t )
2020-04-23 13:02:01 +00:00
data := checkErrGetResult ( t , body , false )
require . NoError ( t , json . Unmarshal ( data , actual ) )
require . Equal ( t , expected , actual )
}
t . Run ( "no verbose" , func ( t * testing . T ) {
w := io . NewBufBinWriter ( )
hdr . EncodeBinary ( w . BinWriter )
require . NoError ( t , w . Err )
2020-11-06 14:37:58 +00:00
encoded := base64 . StdEncoding . EncodeToString ( w . Bytes ( ) )
2020-04-23 13:02:01 +00:00
t . Run ( "missing" , func ( t * testing . T ) {
runCase ( t , fmt . Sprintf ( rpc , ` [" ` + testHeaderHash + ` "] ` ) , & encoded , new ( string ) )
} )
t . Run ( "verbose=0" , func ( t * testing . T ) {
runCase ( t , fmt . Sprintf ( rpc , ` [" ` + testHeaderHash + ` ", 0] ` ) , & encoded , new ( string ) )
} )
2020-06-05 13:02:55 +00:00
t . Run ( "by number" , func ( t * testing . T ) {
runCase ( t , fmt . Sprintf ( rpc , ` [1] ` ) , & encoded , new ( string ) )
} )
2020-04-23 13:02:01 +00:00
} )
t . Run ( "verbose != 0" , func ( t * testing . T ) {
nextHash := chain . GetHeaderHash ( int ( hdr . Index ) + 1 )
expected := & result . Header {
2021-09-09 13:13:59 +00:00
Header : * hdr ,
BlockMetadata : result . BlockMetadata {
Size : io . GetVarSize ( hdr ) ,
NextBlockHash : & nextHash ,
Confirmations : e . chain . BlockHeight ( ) - hdr . Index + 1 ,
} ,
2020-04-23 13:02:01 +00:00
}
rpc := fmt . Sprintf ( rpc , ` [" ` + testHeaderHash + ` ", 2] ` )
runCase ( t , rpc , expected , new ( result . Header ) )
} )
} )
2020-03-02 16:13:44 +00:00
t . Run ( "getrawmempool" , func ( t * testing . T ) {
mp := chain . GetMemPool ( )
// `expected` stores hashes of previously added txs
expected := make ( [ ] util . Uint256 , 0 )
for _ , tx := range mp . GetVerifiedTransactions ( ) {
2020-06-05 16:01:10 +00:00
expected = append ( expected , tx . Hash ( ) )
2020-03-02 16:13:44 +00:00
}
for i := 0 ; i < 5 ; i ++ {
2021-03-25 16:18:01 +00:00
tx := transaction . New ( [ ] byte { byte ( opcode . PUSH1 ) } , 0 )
2020-07-29 16:57:38 +00:00
tx . Signers = [ ] transaction . Signer { { Account : util . Uint160 { 1 , 2 , 3 } } }
2020-03-02 16:13:44 +00:00
assert . NoError ( t , mp . Add ( tx , & FeerStub { } ) )
expected = append ( expected , tx . Hash ( ) )
}
rpc := ` { "jsonrpc": "2.0", "id": 1, "method": "getrawmempool", "params": []} `
2020-04-29 12:14:56 +00:00
body := doRPCCall ( rpc , httpSrv . URL , t )
2020-03-02 16:13:44 +00:00
res := checkErrGetResult ( t , body , false )
var actual [ ] util . Uint256
err := json . Unmarshal ( res , & actual )
require . NoErrorf ( t , err , "could not parse response: %s" , res )
assert . ElementsMatch ( t , expected , actual )
} )
2020-08-07 06:42:44 +00:00
2020-11-24 08:14:25 +00:00
t . Run ( "getnep17transfers" , func ( t * testing . T ) {
testNEP17T := func ( t * testing . T , start , stop , limit , page int , sent , rcvd [ ] int ) {
2020-09-12 21:12:45 +00:00
ps := [ ] string { ` " ` + testchain . PrivateKeyByID ( 0 ) . Address ( ) + ` " ` }
if start != 0 {
h , err := e . chain . GetHeader ( e . chain . GetHeaderHash ( start ) )
var ts uint64
if err == nil {
ts = h . Timestamp
} else {
ts = uint64 ( time . Now ( ) . UnixNano ( ) / 1_000_000 )
}
ps = append ( ps , strconv . FormatUint ( ts , 10 ) )
}
if stop != 0 {
h , err := e . chain . GetHeader ( e . chain . GetHeaderHash ( stop ) )
var ts uint64
if err == nil {
ts = h . Timestamp
} else {
ts = uint64 ( time . Now ( ) . UnixNano ( ) / 1_000_000 )
}
ps = append ( ps , strconv . FormatUint ( ts , 10 ) )
}
if limit != 0 {
ps = append ( ps , strconv . FormatInt ( int64 ( limit ) , 10 ) )
}
if page != 0 {
ps = append ( ps , strconv . FormatInt ( int64 ( page ) , 10 ) )
}
p := strings . Join ( ps , ", " )
2020-11-24 08:14:25 +00:00
rpc := fmt . Sprintf ( ` { "jsonrpc": "2.0", "id": 1, "method": "getnep17transfers", "params": [%s]} ` , p )
2020-09-12 21:12:45 +00:00
body := doRPCCall ( rpc , httpSrv . URL , t )
res := checkErrGetResult ( t , body , false )
2020-11-24 08:14:25 +00:00
actual := new ( result . NEP17Transfers )
2020-09-12 21:12:45 +00:00
require . NoError ( t , json . Unmarshal ( res , actual ) )
2020-11-24 08:14:25 +00:00
checkNep17TransfersAux ( t , e , actual , sent , rcvd )
2020-09-12 21:12:45 +00:00
}
2022-06-15 18:23:29 +00:00
t . Run ( "time frame only" , func ( t * testing . T ) { testNEP17T ( t , 4 , 5 , 0 , 0 , [ ] int { 18 , 19 , 20 , 21 } , [ ] int { 3 , 4 } ) } )
2020-11-24 08:14:25 +00:00
t . Run ( "no res" , func ( t * testing . T ) { testNEP17T ( t , 100 , 100 , 0 , 0 , [ ] int { } , [ ] int { } ) } )
2022-06-15 18:23:29 +00:00
t . Run ( "limit" , func ( t * testing . T ) { testNEP17T ( t , 1 , 7 , 3 , 0 , [ ] int { 15 , 16 } , [ ] int { 2 } ) } )
t . Run ( "limit 2" , func ( t * testing . T ) { testNEP17T ( t , 4 , 5 , 2 , 0 , [ ] int { 18 } , [ ] int { 3 } ) } )
t . Run ( "limit with page" , func ( t * testing . T ) { testNEP17T ( t , 1 , 7 , 3 , 1 , [ ] int { 17 , 18 } , [ ] int { 3 } ) } )
t . Run ( "limit with page 2" , func ( t * testing . T ) { testNEP17T ( t , 1 , 7 , 3 , 2 , [ ] int { 19 , 20 } , [ ] int { 4 } ) } )
} )
prepareIteratorSession := func ( t * testing . T ) ( uuid . UUID , uuid . UUID ) {
rpc := fmt . Sprintf ( ` { "jsonrpc": "2.0", "id": 1, "method": "invokefunction", "params": ["%s", "iterateOverValues"]}" ` , storageContractHash )
body := doRPCCall ( rpc , httpSrv . URL , t )
resp := checkErrGetResult ( t , body , false )
res := new ( result . Invoke )
err := json . Unmarshal ( resp , & res )
require . NoErrorf ( t , err , "could not parse response: %s" , resp )
require . NotEmpty ( t , res . Session )
require . Equal ( t , 1 , len ( res . Stack ) )
require . Equal ( t , stackitem . InteropT , res . Stack [ 0 ] . Type ( ) )
iterator , ok := res . Stack [ 0 ] . Value ( ) . ( result . Iterator )
require . True ( t , ok )
require . NotEmpty ( t , iterator . ID )
return res . Session , * iterator . ID
}
t . Run ( "traverseiterator" , func ( t * testing . T ) {
t . Run ( "good" , func ( t * testing . T ) {
sID , iID := prepareIteratorSession ( t )
expectedCount := 99
rpc := fmt . Sprintf ( ` { "jsonrpc": "2.0", "id": 1, "method": "traverseiterator", "params": ["%s", "%s", %d]}" ` , sID . String ( ) , iID . String ( ) , expectedCount )
body := doRPCCall ( rpc , httpSrv . URL , t )
resp := checkErrGetResult ( t , body , false )
res := new ( [ ] json . RawMessage )
require . NoError ( t , json . Unmarshal ( resp , res ) )
require . Equal ( t , expectedCount , len ( * res ) )
} )
t . Run ( "invalid session id" , func ( t * testing . T ) {
_ , iID := prepareIteratorSession ( t )
rpc := fmt . Sprintf ( ` { "jsonrpc": "2.0", "id": 1, "method": "traverseiterator", "params": ["not-a-uuid", "%s", %d]}" ` , iID . String ( ) , 1 )
body := doRPCCall ( rpc , httpSrv . URL , t )
checkErrGetResult ( t , body , true , "invalid session ID: not a valid UUID" )
} )
t . Run ( "invalid iterator id" , func ( t * testing . T ) {
sID , _ := prepareIteratorSession ( t )
rpc := fmt . Sprintf ( ` { "jsonrpc": "2.0", "id": 1, "method": "traverseiterator", "params": ["%s", "not-a-uuid", %d]}" ` , sID . String ( ) , 1 )
body := doRPCCall ( rpc , httpSrv . URL , t )
checkErrGetResult ( t , body , true , "invalid iterator ID: not a valid UUID" )
} )
t . Run ( "invalid items count" , func ( t * testing . T ) {
sID , iID := prepareIteratorSession ( t )
rpc := fmt . Sprintf ( ` { "jsonrpc": "2.0", "id": 1, "method": "traverseiterator", "params": ["%s", "%s"]}" ` , sID . String ( ) , iID . String ( ) )
body := doRPCCall ( rpc , httpSrv . URL , t )
checkErrGetResult ( t , body , true , "invalid iterator items count" )
} )
t . Run ( "items count is not an int32" , func ( t * testing . T ) {
sID , iID := prepareIteratorSession ( t )
rpc := fmt . Sprintf ( ` { "jsonrpc": "2.0", "id": 1, "method": "traverseiterator", "params": ["%s", "%s", %d]}" ` , sID . String ( ) , iID . String ( ) , math . MaxInt32 + 1 )
body := doRPCCall ( rpc , httpSrv . URL , t )
checkErrGetResult ( t , body , true , "invalid iterator items count: not an int32" )
} )
t . Run ( "count is out of range" , func ( t * testing . T ) {
sID , iID := prepareIteratorSession ( t )
rpc := fmt . Sprintf ( ` { "jsonrpc": "2.0", "id": 1, "method": "traverseiterator", "params": ["%s", "%s", %d]}" ` , sID . String ( ) , iID . String ( ) , rpcSrv . config . MaxIteratorResultItems + 1 )
body := doRPCCall ( rpc , httpSrv . URL , t )
checkErrGetResult ( t , body , true , fmt . Sprintf ( "iterator items count is out of range (%d at max)" , rpcSrv . config . MaxIteratorResultItems ) )
} )
t . Run ( "unknown session" , func ( t * testing . T ) {
_ , iID := prepareIteratorSession ( t )
rpc := fmt . Sprintf ( ` { "jsonrpc": "2.0", "id": 1, "method": "traverseiterator", "params": ["%s", "%s", %d]}" ` , uuid . NewString ( ) , iID . String ( ) , 1 )
body := doRPCCall ( rpc , httpSrv . URL , t )
resp := checkErrGetResult ( t , body , false )
res := new ( [ ] json . RawMessage )
require . NoError ( t , json . Unmarshal ( resp , res ) )
require . Equal ( t , 0 , len ( * res ) ) // No errors expected, no elements should be returned.
} )
t . Run ( "unknown iterator" , func ( t * testing . T ) {
sID , _ := prepareIteratorSession ( t )
rpc := fmt . Sprintf ( ` { "jsonrpc": "2.0", "id": 1, "method": "traverseiterator", "params": ["%s", "%s", %d]}" ` , sID . String ( ) , uuid . NewString ( ) , 1 )
body := doRPCCall ( rpc , httpSrv . URL , t )
resp := checkErrGetResult ( t , body , false )
res := new ( [ ] json . RawMessage )
require . NoError ( t , json . Unmarshal ( resp , res ) )
require . Equal ( t , 0 , len ( * res ) ) // No errors expected, no elements should be returned.
} )
} )
t . Run ( "terminatesession" , func ( t * testing . T ) {
check := func ( t * testing . T , id string , expected bool ) {
rpc := fmt . Sprintf ( ` { "jsonrpc": "2.0", "id": 1, "method": "terminatesession", "params": ["%s"]}" ` , id )
body := doRPCCall ( rpc , httpSrv . URL , t )
resp := checkErrGetResult ( t , body , false )
res := new ( bool )
require . NoError ( t , json . Unmarshal ( resp , res ) )
require . Equal ( t , expected , * res )
}
t . Run ( "true" , func ( t * testing . T ) {
sID , _ := prepareIteratorSession ( t )
check ( t , sID . String ( ) , true )
} )
t . Run ( "false" , func ( t * testing . T ) {
check ( t , uuid . NewString ( ) , false )
} )
t . Run ( "expired" , func ( t * testing . T ) {
_ , _ = prepareIteratorSession ( t )
// Wait until session is terminated by timer.
require . Eventually ( t , func ( ) bool {
rpcSrv . sessionsLock . Lock ( )
defer rpcSrv . sessionsLock . Unlock ( )
return len ( rpcSrv . sessions ) == 0
} , 2 * time . Duration ( rpcSrv . config . SessionExpirationTime ) * time . Second , 10 * time . Millisecond )
} )
2020-08-07 06:42:44 +00:00
} )
2022-08-22 15:50:35 +00:00
t . Run ( "calculatenetworkfee" , func ( t * testing . T ) {
t . Run ( "no parameters" , func ( t * testing . T ) {
body := doRPCCall ( ` { "jsonrpc": "2.0", "id": 1, "method": "calculatenetworkfee", "params": []}" ` , httpSrv . URL , t )
_ = checkErrGetResult ( t , body , true , "Invalid Params" )
} )
t . Run ( "non-base64 parameter" , func ( t * testing . T ) {
body := doRPCCall ( ` { "jsonrpc": "2.0", "id": 1, "method": "calculatenetworkfee", "params": ["noatbase64"]}" ` , httpSrv . URL , t )
_ = checkErrGetResult ( t , body , true , "Invalid Params" )
} )
t . Run ( "non-transaction parameter" , func ( t * testing . T ) {
body := doRPCCall ( ` { "jsonrpc": "2.0", "id": 1, "method": "calculatenetworkfee", "params": ["bm90IGEgdHJhbnNhY3Rpb24K"]}" ` , httpSrv . URL , t )
_ = checkErrGetResult ( t , body , true , "Invalid Params" )
} )
calcReq := func ( t * testing . T , tx * transaction . Transaction ) [ ] byte {
rpc := fmt . Sprintf ( ` { "jsonrpc": "2.0", "id": 1, "method": "calculatenetworkfee", "params": ["%s"]}" ` , base64 . StdEncoding . EncodeToString ( tx . Bytes ( ) ) )
return doRPCCall ( rpc , httpSrv . URL , t )
}
t . Run ( "non-contract with zero verification" , func ( t * testing . T ) {
tx := & transaction . Transaction {
Script : [ ] byte { byte ( opcode . RET ) } ,
Signers : [ ] transaction . Signer { { Account : util . Uint160 { 1 , 2 , 3 } , Scopes : transaction . CalledByEntry } } ,
Scripts : [ ] transaction . Witness { {
InvocationScript : [ ] byte { } ,
VerificationScript : [ ] byte { } ,
} } ,
}
body := calcReq ( t , tx )
_ = checkErrGetResult ( t , body , true , "signer 0 has no verification script and no deployed contract" )
} )
t . Run ( "contract with no verify" , func ( t * testing . T ) {
tx := & transaction . Transaction {
Script : [ ] byte { byte ( opcode . RET ) } ,
Signers : [ ] transaction . Signer { { Account : nnsHash , Scopes : transaction . CalledByEntry } } ,
Scripts : [ ] transaction . Witness { {
InvocationScript : [ ] byte { } ,
VerificationScript : [ ] byte { } ,
} } ,
}
body := calcReq ( t , tx )
_ = checkErrGetResult ( t , body , true , "signer 0 has no verify method in deployed contract" )
} )
checkCalc := func ( t * testing . T , tx * transaction . Transaction , fee int64 ) {
resp := checkErrGetResult ( t , calcReq ( t , tx ) , false )
res := new ( result . NetworkFee )
require . NoError ( t , json . Unmarshal ( resp , res ) )
require . Equal ( t , fee , res . Value )
}
t . Run ( "simple GAS transfer" , func ( t * testing . T ) {
priv0 := testchain . PrivateKeyByID ( 0 )
script , err := smartcontract . CreateCallWithAssertScript ( chain . UtilityTokenHash ( ) , "transfer" ,
priv0 . GetScriptHash ( ) , priv0 . GetScriptHash ( ) , 1 , nil )
require . NoError ( t , err )
tx := & transaction . Transaction {
Script : script ,
Signers : [ ] transaction . Signer { { Account : priv0 . GetScriptHash ( ) , Scopes : transaction . CalledByEntry } } ,
Scripts : [ ] transaction . Witness { {
InvocationScript : [ ] byte { } ,
VerificationScript : priv0 . PublicKey ( ) . GetVerificationScript ( ) ,
} } ,
}
checkCalc ( t , tx , 1228520 ) // Perfectly matches FeeIsSignatureContractDetailed() C# test.
} )
t . Run ( "multisignature tx" , func ( t * testing . T ) {
priv0 := testchain . PrivateKeyByID ( 0 )
priv1 := testchain . PrivateKeyByID ( 1 )
accScript , err := smartcontract . CreateDefaultMultiSigRedeemScript ( keys . PublicKeys { priv0 . PublicKey ( ) , priv1 . PublicKey ( ) } )
require . NoError ( t , err )
multiAcc := hash . Hash160 ( accScript )
txScript , err := smartcontract . CreateCallWithAssertScript ( chain . UtilityTokenHash ( ) , "transfer" ,
multiAcc , priv0 . GetScriptHash ( ) , 1 , nil )
require . NoError ( t , err )
tx := & transaction . Transaction {
Script : txScript ,
Signers : [ ] transaction . Signer { { Account : multiAcc , Scopes : transaction . CalledByEntry } } ,
Scripts : [ ] transaction . Witness { {
InvocationScript : [ ] byte { } ,
VerificationScript : accScript ,
} } ,
}
checkCalc ( t , tx , 2315100 ) // Perfectly matches FeeIsMultiSigContract() C# test.
} )
checkContract := func ( t * testing . T , verAcc util . Uint160 , invoc [ ] byte , fee int64 ) {
txScript , err := smartcontract . CreateCallWithAssertScript ( chain . UtilityTokenHash ( ) , "transfer" ,
verAcc , verAcc , 1 , nil )
require . NoError ( t , err )
tx := & transaction . Transaction {
Script : txScript ,
Signers : [ ] transaction . Signer { { Account : verAcc , Scopes : transaction . CalledByEntry } } ,
Scripts : [ ] transaction . Witness { {
InvocationScript : invoc ,
VerificationScript : [ ] byte { } ,
} } ,
}
checkCalc ( t , tx , fee )
}
t . Run ( "contract-based verification" , func ( t * testing . T ) {
verAcc , err := util . Uint160DecodeStringLE ( verifyContractHash )
require . NoError ( t , err )
checkContract ( t , verAcc , [ ] byte { } , 636610 ) // No C# match, but we believe it's OK.
} )
t . Run ( "contract-based verification with parameters" , func ( t * testing . T ) {
verAcc , err := util . Uint160DecodeStringLE ( verifyWithArgsContractHash )
require . NoError ( t , err )
checkContract ( t , verAcc , [ ] byte { } , 737530 ) // No C# match, but we believe it's OK and it differs from the one above.
} )
t . Run ( "contract-based verification with invocation script" , func ( t * testing . T ) {
verAcc , err := util . Uint160DecodeStringLE ( verifyWithArgsContractHash )
require . NoError ( t , err )
invocWriter := io . NewBufBinWriter ( )
emit . Bool ( invocWriter . BinWriter , false )
emit . Int ( invocWriter . BinWriter , 5 )
emit . String ( invocWriter . BinWriter , "" )
invocScript := invocWriter . Bytes ( )
checkContract ( t , verAcc , invocScript , 640360 ) // No C# match, but we believe it's OK and it has a specific invocation script overriding anything server-side.
} )
} )
2019-11-21 16:41:28 +00:00
}
2019-01-22 12:14:52 +00:00
2020-04-23 13:02:01 +00:00
func ( e * executor ) getHeader ( s string ) * block . Header {
hash , err := util . Uint256DecodeStringLE ( s )
if err != nil {
panic ( "can not decode hash parameter" )
}
block , err := e . chain . GetBlock ( hash )
if err != nil {
panic ( "unknown block (update block hash)" )
}
2021-03-01 13:44:47 +00:00
return & block . Header
2020-04-23 13:02:01 +00:00
}
2020-04-23 13:32:53 +00:00
func encodeBlock ( t * testing . T , b * block . Block ) string {
w := io . NewBufBinWriter ( )
b . EncodeBinary ( w . BinWriter )
require . NoError ( t , w . Err )
2020-11-12 11:05:20 +00:00
return base64 . StdEncoding . EncodeToString ( w . Bytes ( ) )
2020-04-23 13:32:53 +00:00
}
2019-11-21 16:41:28 +00:00
func ( tc rpcTestCase ) getResultPair ( e * executor ) ( expected interface { } , res interface { } ) {
expected = tc . result ( e )
2020-02-21 12:10:59 +00:00
resVal := reflect . New ( reflect . TypeOf ( expected ) . Elem ( ) )
2020-06-18 09:00:51 +00:00
res = resVal . Interface ( )
return expected , res
2019-09-18 15:21:16 +00:00
}
2019-01-22 12:14:52 +00:00
2022-06-15 18:23:29 +00:00
func checkErrGetResult ( t * testing . T , body [ ] byte , expectingFail bool , expectedErr ... string ) json . RawMessage {
2022-07-22 16:09:29 +00:00
var resp neorpc . Response
2020-02-21 12:10:59 +00:00
err := json . Unmarshal ( body , & resp )
2019-11-21 16:41:28 +00:00
require . Nil ( t , err )
2019-09-24 15:47:23 +00:00
if expectingFail {
2020-05-06 10:10:32 +00:00
require . NotNil ( t , resp . Error )
2020-02-21 12:10:59 +00:00
assert . NotEqual ( t , 0 , resp . Error . Code )
assert . NotEqual ( t , "" , resp . Error . Message )
2022-06-15 18:23:29 +00:00
if len ( expectedErr ) != 0 {
assert . True ( t , strings . Contains ( resp . Error . Error ( ) , expectedErr [ 0 ] ) , fmt . Sprintf ( "expected: %s, got: %s" , expectedErr [ 0 ] , resp . Error . Error ( ) ) )
}
2019-09-24 15:47:23 +00:00
} else {
2020-02-21 12:10:59 +00:00
assert . Nil ( t , resp . Error )
2019-09-24 15:47:23 +00:00
}
2020-02-21 12:10:59 +00:00
return resp . Result
2019-09-24 15:47:23 +00:00
}
2020-10-26 17:22:20 +00:00
func checkErrGetBatchResult ( t * testing . T , body [ ] byte , expectingFail bool ) json . RawMessage {
2022-07-22 16:09:29 +00:00
var resp [ ] neorpc . Response
2020-10-26 17:22:20 +00:00
err := json . Unmarshal ( body , & resp )
require . Nil ( t , err )
require . Equal ( t , 1 , len ( resp ) )
if expectingFail {
require . NotNil ( t , resp [ 0 ] . Error )
assert . NotEqual ( t , 0 , resp [ 0 ] . Error . Code )
assert . NotEqual ( t , "" , resp [ 0 ] . Error . Message )
} else {
assert . Nil ( t , resp [ 0 ] . Error )
}
return resp [ 0 ] . Result
}
2020-04-29 12:25:58 +00:00
func doRPCCallOverWS ( rpcCall string , url string , t * testing . T ) [ ] byte {
dialer := websocket . Dialer { HandshakeTimeout : time . Second }
url = "ws" + strings . TrimPrefix ( url , "http" )
2022-09-02 09:21:24 +00:00
c , r , err := dialer . Dial ( url + "/ws" , nil )
2020-04-29 12:25:58 +00:00
require . NoError ( t , err )
2022-09-02 09:21:24 +00:00
defer r . Body . Close ( )
2021-05-12 18:34:07 +00:00
err = c . SetWriteDeadline ( time . Now ( ) . Add ( time . Second ) )
require . NoError ( t , err )
2020-04-29 12:25:58 +00:00
require . NoError ( t , c . WriteMessage ( 1 , [ ] byte ( rpcCall ) ) )
2021-05-12 18:34:07 +00:00
err = c . SetReadDeadline ( time . Now ( ) . Add ( time . Second ) )
require . NoError ( t , err )
2020-04-29 12:25:58 +00:00
_ , body , err := c . ReadMessage ( )
require . NoError ( t , err )
2020-09-16 09:51:59 +00:00
require . NoError ( t , c . Close ( ) )
2020-04-29 12:25:58 +00:00
return bytes . TrimSpace ( body )
}
func doRPCCallOverHTTP ( rpcCall string , url string , t * testing . T ) [ ] byte {
2020-04-29 12:14:56 +00:00
cl := http . Client { Timeout : time . Second }
resp , err := cl . Post ( url , "application/json" , strings . NewReader ( rpcCall ) )
require . NoErrorf ( t , err , "could not make a POST request" )
2022-02-22 16:27:32 +00:00
body , err := gio . ReadAll ( resp . Body )
2022-09-02 09:21:24 +00:00
resp . Body . Close ( )
2019-09-18 15:21:16 +00:00
assert . NoErrorf ( t , err , "could not read response from the request: %s" , rpcCall )
2019-11-21 15:05:18 +00:00
return bytes . TrimSpace ( body )
2019-01-22 12:14:52 +00:00
}
2020-07-03 15:10:07 +00:00
2022-02-04 16:21:12 +00:00
func checkNep11Balances ( t * testing . T , e * executor , acc interface { } ) {
res , ok := acc . ( * result . NEP11Balances )
require . True ( t , ok )
expected := result . NEP11Balances {
Balances : [ ] result . NEP11AssetBalance {
{
2022-07-04 14:12:42 +00:00
Asset : nnsHash ,
Name : "NameService" ,
Symbol : "NNS" ,
2022-02-04 16:21:12 +00:00
Tokens : [ ] result . NEP11TokenBalance {
{
ID : nnsToken1ID ,
Amount : "1" ,
LastUpdated : 14 ,
} ,
} ,
} ,
{
2022-07-04 14:12:42 +00:00
Asset : nfsoHash ,
Decimals : 2 ,
Name : "NeoFS Object NFT" ,
Symbol : "NFSO" ,
2022-02-04 16:21:12 +00:00
Tokens : [ ] result . NEP11TokenBalance {
{
ID : nfsoToken1ID ,
Amount : "80" ,
LastUpdated : 21 ,
} ,
} ,
} ,
} ,
Address : testchain . PrivateKeyByID ( 0 ) . GetScriptHash ( ) . StringLE ( ) ,
}
require . Equal ( t , testchain . PrivateKeyByID ( 0 ) . Address ( ) , res . Address )
require . ElementsMatch ( t , expected . Balances , res . Balances )
}
2020-11-24 08:14:25 +00:00
func checkNep17Balances ( t * testing . T , e * executor , acc interface { } ) {
res , ok := acc . ( * result . NEP17Balances )
2020-07-03 15:10:07 +00:00
require . True ( t , ok )
rubles , err := util . Uint160DecodeStringLE ( testContractHash )
require . NoError ( t , err )
2020-11-24 08:14:25 +00:00
expected := result . NEP17Balances {
Balances : [ ] result . NEP17Balance {
2020-07-03 15:10:07 +00:00
{
Asset : rubles ,
rpc: adjust NEP5 transfers amount JSON marshalling
This committ fixes the difference between Go and C# nodes:
Go:
```
{
"jsonrpc" : "2.0",
"result" : {
"received" : [
{
"blockindex" : 65,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"transfernotifyindex" : 0,
"timestamp" : 1605535020126,
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"amount" : "29999999",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
],
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : []
},
"id" : 1
}
```
C#:
```
{
"id" : 1,
"result" : {
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : [],
"received" : [
{
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"timestamp" : 1605535020126,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"blockindex" : 65,
"transfernotifyindex" : 0,
"amount" : "2999999900000000",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
]
},
"jsonrpc" : "2.0"
}
```
2020-11-17 09:28:28 +00:00
Amount : "877" ,
2022-07-04 14:12:42 +00:00
Decimals : 2 ,
2020-07-03 15:10:07 +00:00
LastUpdated : 6 ,
2022-07-04 14:12:42 +00:00
Name : "Rubl" ,
Symbol : "RUB" ,
2020-07-03 15:10:07 +00:00
} ,
{
Asset : e . chain . GoverningTokenHash ( ) ,
Amount : "99998000" ,
LastUpdated : 4 ,
2022-07-04 14:12:42 +00:00
Name : "NeoToken" ,
Symbol : "NEO" ,
2020-07-03 15:10:07 +00:00
} ,
{
Asset : e . chain . UtilityTokenHash ( ) ,
2022-07-28 13:56:48 +00:00
Amount : "37099660700" ,
2022-06-15 18:23:29 +00:00
LastUpdated : 22 ,
2022-07-04 14:12:42 +00:00
Decimals : 8 ,
Name : "GasToken" ,
Symbol : "GAS" ,
2020-07-03 15:10:07 +00:00
} } ,
Address : testchain . PrivateKeyByID ( 0 ) . GetScriptHash ( ) . StringLE ( ) ,
}
require . Equal ( t , testchain . PrivateKeyByID ( 0 ) . Address ( ) , res . Address )
require . ElementsMatch ( t , expected . Balances , res . Balances )
}
2020-07-03 15:25:18 +00:00
2022-02-04 16:21:12 +00:00
func checkNep11Transfers ( t * testing . T , e * executor , acc interface { } ) {
checkNep11TransfersAux ( t , e , acc , [ ] int { 0 } , [ ] int { 0 , 1 , 2 } )
}
func checkNep11TransfersAux ( t * testing . T , e * executor , acc interface { } , sent , rcvd [ ] int ) {
res , ok := acc . ( * result . NEP11Transfers )
require . True ( t , ok )
blockReceiveNFSO , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 21 ) ) // transfer 0.05 NFSO from priv1 back to priv0.
require . NoError ( t , err )
require . Equal ( t , 1 , len ( blockReceiveNFSO . Transactions ) )
txReceiveNFSO := blockReceiveNFSO . Transactions [ 0 ]
blockSendNFSO , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 19 ) ) // transfer 0.25 NFSO from priv0 to priv1.
require . NoError ( t , err )
require . Equal ( t , 1 , len ( blockSendNFSO . Transactions ) )
txSendNFSO := blockSendNFSO . Transactions [ 0 ]
blockMintNFSO , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 18 ) ) // mint 1.00 NFSO token by transferring 10 GAS to NFSO contract.
require . NoError ( t , err )
require . Equal ( t , 1 , len ( blockMintNFSO . Transactions ) )
txMintNFSO := blockMintNFSO . Transactions [ 0 ]
blockRegisterNSRecordA , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 14 ) ) // register `neo.com` with A record type and priv0 owner via NS
require . NoError ( t , err )
require . Equal ( t , 1 , len ( blockRegisterNSRecordA . Transactions ) )
txRegisterNSRecordA := blockRegisterNSRecordA . Transactions [ 0 ]
// These are laid out here explicitly for 2 purposes:
// * to be able to reference any particular event for paging
// * to check chain events consistency
// Technically these could be retrieved from application log, but that would almost
// duplicate the Server method.
expected := result . NEP11Transfers {
Sent : [ ] result . NEP11Transfer {
{
Timestamp : blockSendNFSO . Timestamp ,
Asset : nfsoHash ,
Address : testchain . PrivateKeyByID ( 1 ) . Address ( ) , // to priv1
ID : nfsoToken1ID , // NFSO ID
Amount : big . NewInt ( 25 ) . String ( ) ,
Index : 19 ,
TxHash : txSendNFSO . Hash ( ) ,
} ,
} ,
Received : [ ] result . NEP11Transfer {
{
Timestamp : blockReceiveNFSO . Timestamp ,
Asset : nfsoHash ,
ID : nfsoToken1ID ,
Address : testchain . PrivateKeyByID ( 1 ) . Address ( ) , // from priv1
Amount : "5" ,
Index : 21 ,
TxHash : txReceiveNFSO . Hash ( ) ,
} ,
{
Timestamp : blockMintNFSO . Timestamp ,
Asset : nfsoHash ,
ID : nfsoToken1ID ,
Address : "" , // minting
Amount : "100" ,
Index : 18 ,
TxHash : txMintNFSO . Hash ( ) ,
} ,
{
Timestamp : blockRegisterNSRecordA . Timestamp ,
Asset : nnsHash ,
ID : nnsToken1ID ,
Address : "" , // minting
Amount : "1" ,
Index : 14 ,
TxHash : txRegisterNSRecordA . Hash ( ) ,
} ,
} ,
Address : testchain . PrivateKeyByID ( 0 ) . Address ( ) ,
}
require . Equal ( t , expected . Address , res . Address )
arr := make ( [ ] result . NEP11Transfer , 0 , len ( expected . Sent ) )
for i := range expected . Sent {
for _ , j := range sent {
if i == j {
arr = append ( arr , expected . Sent [ i ] )
break
}
}
}
require . Equal ( t , arr , res . Sent )
arr = arr [ : 0 ]
for i := range expected . Received {
for _ , j := range rcvd {
if i == j {
arr = append ( arr , expected . Received [ i ] )
break
}
}
}
require . Equal ( t , arr , res . Received )
}
2020-11-24 08:14:25 +00:00
func checkNep17Transfers ( t * testing . T , e * executor , acc interface { } ) {
2022-06-15 18:23:29 +00:00
checkNep17TransfersAux ( t , e , acc , [ ] int { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 } , [ ] int { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 } )
2020-08-07 06:42:44 +00:00
}
2020-11-24 08:14:25 +00:00
func checkNep17TransfersAux ( t * testing . T , e * executor , acc interface { } , sent , rcvd [ ] int ) {
res , ok := acc . ( * result . NEP17Transfers )
2020-07-03 15:25:18 +00:00
require . True ( t , ok )
rublesHash , err := util . Uint160DecodeStringLE ( testContractHash )
require . NoError ( t , err )
2020-09-12 21:12:45 +00:00
2022-06-15 18:23:29 +00:00
blockDeploy6 , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 22 ) ) // deploy Storage contract (storage_contract.go)
require . NoError ( t , err )
require . Equal ( t , 1 , len ( blockDeploy6 . Transactions ) )
txDeploy6 := blockDeploy6 . Transactions [ 0 ]
2022-02-04 16:21:12 +00:00
blockTransferNFSO , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 19 ) ) // transfer 0.25 NFSO from priv0 to priv1.
require . NoError ( t , err )
require . Equal ( t , 1 , len ( blockTransferNFSO . Transactions ) )
txTransferNFSO := blockTransferNFSO . Transactions [ 0 ]
blockMintNFSO , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 18 ) ) // mint 1.00 NFSO token for priv0 by transferring 10 GAS to NFSO contract.
require . NoError ( t , err )
require . Equal ( t , 1 , len ( blockMintNFSO . Transactions ) )
txMintNFSO := blockMintNFSO . Transactions [ 0 ]
blockDeploy5 , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 17 ) ) // deploy NeoFS Object contract (NEP11-Divisible)
require . NoError ( t , err )
require . Equal ( t , 1 , len ( blockDeploy5 . Transactions ) )
txDeploy5 := blockDeploy5 . Transactions [ 0 ]
2021-10-07 09:03:37 +00:00
blockPutNewTestValue , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 16 ) ) // invoke `put` method of `test_contract.go` with `testkey`, `newtestvalue` args
require . NoError ( t , err )
2022-03-11 10:22:36 +00:00
require . Equal ( t , 4 , len ( blockPutNewTestValue . Transactions ) )
2021-10-07 09:03:37 +00:00
txPutNewTestValue := blockPutNewTestValue . Transactions [ 0 ]
2022-03-11 10:22:36 +00:00
txPutValue1 := blockPutNewTestValue . Transactions [ 1 ] // invoke `put` method of `test_contract.go` with `aa`, `v1` args
txPutValue2 := blockPutNewTestValue . Transactions [ 2 ] // invoke `put` method of `test_contract.go` with `aa10`, `v2` args
txPutValue3 := blockPutNewTestValue . Transactions [ 3 ] // invoke `put` method of `test_contract.go` with `aa50`, `v3` args
2021-10-07 09:03:37 +00:00
2021-05-14 16:38:04 +00:00
blockSetRecord , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 15 ) ) // add type A record to `neo.com` domain via NNS
2021-03-24 12:36:10 +00:00
require . NoError ( t , err )
require . Equal ( t , 1 , len ( blockSetRecord . Transactions ) )
txSetRecord := blockSetRecord . Transactions [ 0 ]
2021-05-14 16:38:04 +00:00
blockRegisterDomain , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 14 ) ) // register `neo.com` domain via NNS
2021-03-24 12:36:10 +00:00
require . NoError ( t , err )
require . Equal ( t , 1 , len ( blockRegisterDomain . Transactions ) )
txRegisterDomain := blockRegisterDomain . Transactions [ 0 ]
blockGASBounty2 , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 12 ) ) // size of committee = 6
require . NoError ( t , err )
2021-05-14 16:38:04 +00:00
blockDeploy4 , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 11 ) ) // deploy ns.go (non-native neo name service contract)
require . NoError ( t , err )
require . Equal ( t , 1 , len ( blockDeploy4 . Transactions ) )
txDeploy4 := blockDeploy4 . Transactions [ 0 ]
2021-03-10 14:43:52 +00:00
blockDeploy3 , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 10 ) ) // deploy verification_with_args_contract.go
require . NoError ( t , err )
require . Equal ( t , 1 , len ( blockDeploy3 . Transactions ) )
txDeploy3 := blockDeploy3 . Transactions [ 0 ]
2021-02-09 09:05:45 +00:00
blockDepositGAS , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 8 ) )
require . NoError ( t , err )
require . Equal ( t , 1 , len ( blockDepositGAS . Transactions ) )
txDepositGAS := blockDepositGAS . Transactions [ 0 ]
2021-03-10 14:43:52 +00:00
blockDeploy2 , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 7 ) ) // deploy verification_contract.go
2020-09-12 21:12:45 +00:00
require . NoError ( t , err )
require . Equal ( t , 1 , len ( blockDeploy2 . Transactions ) )
txDeploy2 := blockDeploy2 . Transactions [ 0 ]
2020-07-03 15:25:18 +00:00
blockSendRubles , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 6 ) )
require . NoError ( t , err )
require . Equal ( t , 1 , len ( blockSendRubles . Transactions ) )
2020-09-12 21:12:45 +00:00
txSendRubles := blockSendRubles . Transactions [ 0 ]
2021-03-24 12:36:10 +00:00
blockGASBounty1 := blockSendRubles // index 6 = size of committee
2020-09-12 21:12:45 +00:00
2020-07-03 15:25:18 +00:00
blockReceiveRubles , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 5 ) )
require . NoError ( t , err )
require . Equal ( t , 2 , len ( blockReceiveRubles . Transactions ) )
2020-09-12 21:12:45 +00:00
txInitCall := blockReceiveRubles . Transactions [ 0 ]
txReceiveRubles := blockReceiveRubles . Transactions [ 1 ]
2020-07-03 15:25:18 +00:00
blockSendNEO , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 4 ) )
require . NoError ( t , err )
require . Equal ( t , 1 , len ( blockSendNEO . Transactions ) )
2020-09-12 21:12:45 +00:00
txSendNEO := blockSendNEO . Transactions [ 0 ]
blockCtrInv1 , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 3 ) )
require . NoError ( t , err )
require . Equal ( t , 1 , len ( blockCtrInv1 . Transactions ) )
txCtrInv1 := blockCtrInv1 . Transactions [ 0 ]
blockCtrDeploy , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 2 ) )
require . NoError ( t , err )
require . Equal ( t , 1 , len ( blockCtrDeploy . Transactions ) )
txCtrDeploy := blockCtrDeploy . Transactions [ 0 ]
blockReceiveGAS , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 1 ) )
require . NoError ( t , err )
require . Equal ( t , 2 , len ( blockReceiveGAS . Transactions ) )
txReceiveNEO := blockReceiveGAS . Transactions [ 0 ]
txReceiveGAS := blockReceiveGAS . Transactions [ 1 ]
2020-09-23 08:48:31 +00:00
blockGASBounty0 , err := e . chain . GetBlock ( e . chain . GetHeaderHash ( 0 ) )
require . NoError ( t , err )
2020-09-12 21:12:45 +00:00
// These are laid out here explicitly for 2 purposes:
// * to be able to reference any particular event for paging
// * to check chain events consistency
// Technically these could be retrieved from application log, but that would almost
// duplicate the Server method.
2020-11-24 08:14:25 +00:00
expected := result . NEP17Transfers {
Sent : [ ] result . NEP17Transfer {
2022-06-15 18:23:29 +00:00
{
Timestamp : blockDeploy6 . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" , // burn
Amount : big . NewInt ( txDeploy6 . SystemFee + txDeploy6 . NetworkFee ) . String ( ) ,
Index : 22 ,
TxHash : blockDeploy6 . Hash ( ) ,
} ,
2022-02-04 16:21:12 +00:00
{
Timestamp : blockTransferNFSO . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" , // burn
Amount : big . NewInt ( txTransferNFSO . SystemFee + txTransferNFSO . NetworkFee ) . String ( ) ,
Index : 19 ,
TxHash : blockTransferNFSO . Hash ( ) ,
} ,
{
Timestamp : blockMintNFSO . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : address . Uint160ToString ( nfsoHash ) ,
Amount : "1000000000" ,
Index : 18 ,
NotifyIndex : 0 ,
TxHash : txMintNFSO . Hash ( ) ,
} ,
{
Timestamp : blockMintNFSO . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" , // burn
Amount : big . NewInt ( txMintNFSO . SystemFee + txMintNFSO . NetworkFee ) . String ( ) ,
Index : 18 ,
TxHash : blockMintNFSO . Hash ( ) ,
} ,
{
Timestamp : blockDeploy5 . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" , // burn
Amount : big . NewInt ( txDeploy5 . SystemFee + txDeploy5 . NetworkFee ) . String ( ) ,
Index : 17 ,
TxHash : blockDeploy5 . Hash ( ) ,
} ,
2022-03-11 10:22:36 +00:00
{
Timestamp : blockPutNewTestValue . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" , // burn
Amount : big . NewInt ( txPutValue3 . SystemFee + txPutValue3 . NetworkFee ) . String ( ) ,
Index : 16 ,
TxHash : blockPutNewTestValue . Hash ( ) ,
} ,
{
Timestamp : blockPutNewTestValue . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" , // burn
Amount : big . NewInt ( txPutValue2 . SystemFee + txPutValue2 . NetworkFee ) . String ( ) ,
Index : 16 ,
TxHash : blockPutNewTestValue . Hash ( ) ,
} ,
{
Timestamp : blockPutNewTestValue . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" , // burn
Amount : big . NewInt ( txPutValue1 . SystemFee + txPutValue1 . NetworkFee ) . String ( ) ,
Index : 16 ,
TxHash : blockPutNewTestValue . Hash ( ) ,
} ,
2021-10-07 09:03:37 +00:00
{
Timestamp : blockPutNewTestValue . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" , // burn
Amount : big . NewInt ( txPutNewTestValue . SystemFee + txPutNewTestValue . NetworkFee ) . String ( ) ,
Index : 16 ,
TxHash : blockPutNewTestValue . Hash ( ) ,
} ,
2021-03-24 12:36:10 +00:00
{
Timestamp : blockSetRecord . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" , // burn
Amount : big . NewInt ( txSetRecord . SystemFee + txSetRecord . NetworkFee ) . String ( ) ,
2021-05-14 16:38:04 +00:00
Index : 15 ,
2021-03-24 12:36:10 +00:00
TxHash : blockSetRecord . Hash ( ) ,
} ,
{
Timestamp : blockRegisterDomain . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" , // burn
Amount : big . NewInt ( txRegisterDomain . SystemFee + txRegisterDomain . NetworkFee ) . String ( ) ,
2021-05-14 16:38:04 +00:00
Index : 14 ,
2021-03-24 12:36:10 +00:00
TxHash : blockRegisterDomain . Hash ( ) ,
} ,
2021-05-14 16:38:04 +00:00
{
Timestamp : blockDeploy4 . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" , // burn
Amount : big . NewInt ( txDeploy4 . SystemFee + txDeploy4 . NetworkFee ) . String ( ) ,
Index : 11 ,
TxHash : blockDeploy4 . Hash ( ) ,
} ,
2021-03-10 14:43:52 +00:00
{
Timestamp : blockDeploy3 . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" , // burn
Amount : big . NewInt ( txDeploy3 . SystemFee + txDeploy3 . NetworkFee ) . String ( ) ,
Index : 10 ,
TxHash : blockDeploy3 . Hash ( ) ,
} ,
2021-02-09 09:05:45 +00:00
{
Timestamp : blockDepositGAS . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : address . Uint160ToString ( e . chain . GetNotaryContractScriptHash ( ) ) ,
Amount : "1000000000" ,
Index : 8 ,
NotifyIndex : 0 ,
TxHash : txDepositGAS . Hash ( ) ,
} ,
{
Timestamp : blockDepositGAS . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" , // burn
Amount : big . NewInt ( txDepositGAS . SystemFee + txDepositGAS . NetworkFee ) . String ( ) ,
Index : 8 ,
TxHash : blockDepositGAS . Hash ( ) ,
} ,
2020-07-03 15:25:18 +00:00
{
2020-09-12 21:12:45 +00:00
Timestamp : blockDeploy2 . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" , // burn
rpc: adjust NEP5 transfers amount JSON marshalling
This committ fixes the difference between Go and C# nodes:
Go:
```
{
"jsonrpc" : "2.0",
"result" : {
"received" : [
{
"blockindex" : 65,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"transfernotifyindex" : 0,
"timestamp" : 1605535020126,
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"amount" : "29999999",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
],
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : []
},
"id" : 1
}
```
C#:
```
{
"id" : 1,
"result" : {
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : [],
"received" : [
{
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"timestamp" : 1605535020126,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"blockindex" : 65,
"transfernotifyindex" : 0,
"amount" : "2999999900000000",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
]
},
"jsonrpc" : "2.0"
}
```
2020-11-17 09:28:28 +00:00
Amount : big . NewInt ( txDeploy2 . SystemFee + txDeploy2 . NetworkFee ) . String ( ) ,
2020-09-12 21:12:45 +00:00
Index : 7 ,
TxHash : blockDeploy2 . Hash ( ) ,
2020-07-03 15:25:18 +00:00
} ,
2020-08-07 06:42:44 +00:00
{
Timestamp : blockSendRubles . Timestamp ,
Asset : rublesHash ,
Address : testchain . PrivateKeyByID ( 1 ) . Address ( ) ,
rpc: adjust NEP5 transfers amount JSON marshalling
This committ fixes the difference between Go and C# nodes:
Go:
```
{
"jsonrpc" : "2.0",
"result" : {
"received" : [
{
"blockindex" : 65,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"transfernotifyindex" : 0,
"timestamp" : 1605535020126,
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"amount" : "29999999",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
],
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : []
},
"id" : 1
}
```
C#:
```
{
"id" : 1,
"result" : {
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : [],
"received" : [
{
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"timestamp" : 1605535020126,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"blockindex" : 65,
"transfernotifyindex" : 0,
"amount" : "2999999900000000",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
]
},
"jsonrpc" : "2.0"
}
```
2020-11-17 09:28:28 +00:00
Amount : "123" ,
2020-08-07 06:42:44 +00:00
Index : 6 ,
NotifyIndex : 0 ,
2020-09-12 21:12:45 +00:00
TxHash : txSendRubles . Hash ( ) ,
} ,
{
Timestamp : blockSendRubles . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" , // burn
rpc: adjust NEP5 transfers amount JSON marshalling
This committ fixes the difference between Go and C# nodes:
Go:
```
{
"jsonrpc" : "2.0",
"result" : {
"received" : [
{
"blockindex" : 65,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"transfernotifyindex" : 0,
"timestamp" : 1605535020126,
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"amount" : "29999999",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
],
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : []
},
"id" : 1
}
```
C#:
```
{
"id" : 1,
"result" : {
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : [],
"received" : [
{
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"timestamp" : 1605535020126,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"blockindex" : 65,
"transfernotifyindex" : 0,
"amount" : "2999999900000000",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
]
},
"jsonrpc" : "2.0"
}
```
2020-11-17 09:28:28 +00:00
Amount : big . NewInt ( txSendRubles . SystemFee + txSendRubles . NetworkFee ) . String ( ) ,
2020-09-12 21:12:45 +00:00
Index : 6 ,
TxHash : blockSendRubles . Hash ( ) ,
} ,
{
Timestamp : blockReceiveRubles . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" , // burn
rpc: adjust NEP5 transfers amount JSON marshalling
This committ fixes the difference between Go and C# nodes:
Go:
```
{
"jsonrpc" : "2.0",
"result" : {
"received" : [
{
"blockindex" : 65,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"transfernotifyindex" : 0,
"timestamp" : 1605535020126,
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"amount" : "29999999",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
],
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : []
},
"id" : 1
}
```
C#:
```
{
"id" : 1,
"result" : {
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : [],
"received" : [
{
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"timestamp" : 1605535020126,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"blockindex" : 65,
"transfernotifyindex" : 0,
"amount" : "2999999900000000",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
]
},
"jsonrpc" : "2.0"
}
```
2020-11-17 09:28:28 +00:00
Amount : big . NewInt ( txReceiveRubles . SystemFee + txReceiveRubles . NetworkFee ) . String ( ) ,
2020-09-12 21:12:45 +00:00
Index : 5 ,
TxHash : blockReceiveRubles . Hash ( ) ,
} ,
{
Timestamp : blockReceiveRubles . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" , // burn
rpc: adjust NEP5 transfers amount JSON marshalling
This committ fixes the difference between Go and C# nodes:
Go:
```
{
"jsonrpc" : "2.0",
"result" : {
"received" : [
{
"blockindex" : 65,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"transfernotifyindex" : 0,
"timestamp" : 1605535020126,
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"amount" : "29999999",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
],
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : []
},
"id" : 1
}
```
C#:
```
{
"id" : 1,
"result" : {
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : [],
"received" : [
{
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"timestamp" : 1605535020126,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"blockindex" : 65,
"transfernotifyindex" : 0,
"amount" : "2999999900000000",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
]
},
"jsonrpc" : "2.0"
}
```
2020-11-17 09:28:28 +00:00
Amount : big . NewInt ( txInitCall . SystemFee + txInitCall . NetworkFee ) . String ( ) ,
2020-09-12 21:12:45 +00:00
Index : 5 ,
TxHash : blockReceiveRubles . Hash ( ) ,
} ,
{
Timestamp : blockSendNEO . Timestamp ,
Asset : e . chain . GoverningTokenHash ( ) ,
Address : testchain . PrivateKeyByID ( 1 ) . Address ( ) ,
Amount : "1000" ,
Index : 4 ,
NotifyIndex : 0 ,
TxHash : txSendNEO . Hash ( ) ,
} ,
{
Timestamp : blockSendNEO . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" , // burn
rpc: adjust NEP5 transfers amount JSON marshalling
This committ fixes the difference between Go and C# nodes:
Go:
```
{
"jsonrpc" : "2.0",
"result" : {
"received" : [
{
"blockindex" : 65,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"transfernotifyindex" : 0,
"timestamp" : 1605535020126,
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"amount" : "29999999",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
],
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : []
},
"id" : 1
}
```
C#:
```
{
"id" : 1,
"result" : {
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : [],
"received" : [
{
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"timestamp" : 1605535020126,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"blockindex" : 65,
"transfernotifyindex" : 0,
"amount" : "2999999900000000",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
]
},
"jsonrpc" : "2.0"
}
```
2020-11-17 09:28:28 +00:00
Amount : big . NewInt ( txSendNEO . SystemFee + txSendNEO . NetworkFee ) . String ( ) ,
2020-09-12 21:12:45 +00:00
Index : 4 ,
TxHash : blockSendNEO . Hash ( ) ,
} ,
{
Timestamp : blockCtrInv1 . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" , // burn has empty receiver
rpc: adjust NEP5 transfers amount JSON marshalling
This committ fixes the difference between Go and C# nodes:
Go:
```
{
"jsonrpc" : "2.0",
"result" : {
"received" : [
{
"blockindex" : 65,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"transfernotifyindex" : 0,
"timestamp" : 1605535020126,
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"amount" : "29999999",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
],
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : []
},
"id" : 1
}
```
C#:
```
{
"id" : 1,
"result" : {
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : [],
"received" : [
{
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"timestamp" : 1605535020126,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"blockindex" : 65,
"transfernotifyindex" : 0,
"amount" : "2999999900000000",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
]
},
"jsonrpc" : "2.0"
}
```
2020-11-17 09:28:28 +00:00
Amount : big . NewInt ( txCtrInv1 . SystemFee + txCtrInv1 . NetworkFee ) . String ( ) ,
2020-09-12 21:12:45 +00:00
Index : 3 ,
TxHash : blockCtrInv1 . Hash ( ) ,
} ,
{
Timestamp : blockCtrDeploy . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" , // burn has empty receiver
rpc: adjust NEP5 transfers amount JSON marshalling
This committ fixes the difference between Go and C# nodes:
Go:
```
{
"jsonrpc" : "2.0",
"result" : {
"received" : [
{
"blockindex" : 65,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"transfernotifyindex" : 0,
"timestamp" : 1605535020126,
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"amount" : "29999999",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
],
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : []
},
"id" : 1
}
```
C#:
```
{
"id" : 1,
"result" : {
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : [],
"received" : [
{
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"timestamp" : 1605535020126,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"blockindex" : 65,
"transfernotifyindex" : 0,
"amount" : "2999999900000000",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
]
},
"jsonrpc" : "2.0"
}
```
2020-11-17 09:28:28 +00:00
Amount : big . NewInt ( txCtrDeploy . SystemFee + txCtrDeploy . NetworkFee ) . String ( ) ,
2020-09-12 21:12:45 +00:00
Index : 2 ,
TxHash : blockCtrDeploy . Hash ( ) ,
2020-08-07 06:42:44 +00:00
} ,
2020-07-03 15:25:18 +00:00
} ,
2020-11-24 08:14:25 +00:00
Received : [ ] result . NEP17Transfer {
2022-02-04 16:21:12 +00:00
{
Timestamp : blockMintNFSO . Timestamp , // GAS bounty
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" ,
Amount : "50000000" ,
Index : 18 ,
NotifyIndex : 0 ,
TxHash : blockMintNFSO . Hash ( ) ,
} ,
2020-08-26 13:16:57 +00:00
{
2021-03-24 12:36:10 +00:00
Timestamp : blockGASBounty2 . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" ,
Amount : "50000000" ,
Index : 12 ,
NotifyIndex : 0 ,
TxHash : blockGASBounty2 . Hash ( ) ,
} ,
{
Timestamp : blockGASBounty1 . Timestamp ,
2020-08-26 13:16:57 +00:00
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" ,
rpc: adjust NEP5 transfers amount JSON marshalling
This committ fixes the difference between Go and C# nodes:
Go:
```
{
"jsonrpc" : "2.0",
"result" : {
"received" : [
{
"blockindex" : 65,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"transfernotifyindex" : 0,
"timestamp" : 1605535020126,
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"amount" : "29999999",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
],
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : []
},
"id" : 1
}
```
C#:
```
{
"id" : 1,
"result" : {
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : [],
"received" : [
{
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"timestamp" : 1605535020126,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"blockindex" : 65,
"transfernotifyindex" : 0,
"amount" : "2999999900000000",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
]
},
"jsonrpc" : "2.0"
}
```
2020-11-17 09:28:28 +00:00
Amount : "50000000" ,
2020-08-26 13:16:57 +00:00
Index : 6 ,
NotifyIndex : 0 ,
2021-03-24 12:36:10 +00:00
TxHash : blockGASBounty1 . Hash ( ) ,
2020-08-26 13:16:57 +00:00
} ,
2020-07-03 15:25:18 +00:00
{
Timestamp : blockReceiveRubles . Timestamp ,
Asset : rublesHash ,
Address : address . Uint160ToString ( rublesHash ) ,
rpc: adjust NEP5 transfers amount JSON marshalling
This committ fixes the difference between Go and C# nodes:
Go:
```
{
"jsonrpc" : "2.0",
"result" : {
"received" : [
{
"blockindex" : 65,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"transfernotifyindex" : 0,
"timestamp" : 1605535020126,
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"amount" : "29999999",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
],
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : []
},
"id" : 1
}
```
C#:
```
{
"id" : 1,
"result" : {
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : [],
"received" : [
{
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"timestamp" : 1605535020126,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"blockindex" : 65,
"transfernotifyindex" : 0,
"amount" : "2999999900000000",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
]
},
"jsonrpc" : "2.0"
}
```
2020-11-17 09:28:28 +00:00
Amount : "1000" ,
2020-07-03 15:25:18 +00:00
Index : 5 ,
NotifyIndex : 0 ,
2020-09-12 21:12:45 +00:00
TxHash : txReceiveRubles . Hash ( ) ,
2020-07-03 15:25:18 +00:00
} ,
{
Timestamp : blockSendNEO . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" , // Minted GAS.
rpc: adjust NEP5 transfers amount JSON marshalling
This committ fixes the difference between Go and C# nodes:
Go:
```
{
"jsonrpc" : "2.0",
"result" : {
"received" : [
{
"blockindex" : 65,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"transfernotifyindex" : 0,
"timestamp" : 1605535020126,
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"amount" : "29999999",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
],
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : []
},
"id" : 1
}
```
C#:
```
{
"id" : 1,
"result" : {
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : [],
"received" : [
{
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"timestamp" : 1605535020126,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"blockindex" : 65,
"transfernotifyindex" : 0,
"amount" : "2999999900000000",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
]
},
"jsonrpc" : "2.0"
}
```
2020-11-17 09:28:28 +00:00
Amount : "149998500" ,
2020-07-03 15:25:18 +00:00
Index : 4 ,
NotifyIndex : 0 ,
2020-09-12 21:12:45 +00:00
TxHash : txSendNEO . Hash ( ) ,
2020-07-03 15:25:18 +00:00
} ,
{
Timestamp : blockReceiveGAS . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : testchain . MultisigAddress ( ) ,
rpc: adjust NEP5 transfers amount JSON marshalling
This committ fixes the difference between Go and C# nodes:
Go:
```
{
"jsonrpc" : "2.0",
"result" : {
"received" : [
{
"blockindex" : 65,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"transfernotifyindex" : 0,
"timestamp" : 1605535020126,
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"amount" : "29999999",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
],
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : []
},
"id" : 1
}
```
C#:
```
{
"id" : 1,
"result" : {
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : [],
"received" : [
{
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"timestamp" : 1605535020126,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"blockindex" : 65,
"transfernotifyindex" : 0,
"amount" : "2999999900000000",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
]
},
"jsonrpc" : "2.0"
}
```
2020-11-17 09:28:28 +00:00
Amount : "100000000000" ,
2020-07-03 15:25:18 +00:00
Index : 1 ,
NotifyIndex : 0 ,
2020-09-12 21:12:45 +00:00
TxHash : txReceiveGAS . Hash ( ) ,
2020-07-03 15:25:18 +00:00
} ,
{
Timestamp : blockReceiveGAS . Timestamp ,
Asset : e . chain . GoverningTokenHash ( ) ,
Address : testchain . MultisigAddress ( ) ,
Amount : "99999000" ,
Index : 1 ,
NotifyIndex : 0 ,
2020-09-12 21:12:45 +00:00
TxHash : txReceiveNEO . Hash ( ) ,
2020-07-03 15:25:18 +00:00
} ,
2020-09-23 08:48:31 +00:00
{
Timestamp : blockGASBounty0 . Timestamp ,
Asset : e . chain . UtilityTokenHash ( ) ,
Address : "" ,
rpc: adjust NEP5 transfers amount JSON marshalling
This committ fixes the difference between Go and C# nodes:
Go:
```
{
"jsonrpc" : "2.0",
"result" : {
"received" : [
{
"blockindex" : 65,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"transfernotifyindex" : 0,
"timestamp" : 1605535020126,
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"amount" : "29999999",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
],
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : []
},
"id" : 1
}
```
C#:
```
{
"id" : 1,
"result" : {
"address" : "NULwe3UAHckN2fzNdcVg31tDiaYtMDwANt",
"sent" : [],
"received" : [
{
"transferaddress" : "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY",
"timestamp" : 1605535020126,
"txhash" : "0x394f851cf167d664c0dbcf98e2e64f2da23022fd7943dcb914492529de20a945",
"blockindex" : 65,
"transfernotifyindex" : 0,
"amount" : "2999999900000000",
"assethash" : "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"
}
]
},
"jsonrpc" : "2.0"
}
```
2020-11-17 09:28:28 +00:00
Amount : "50000000" ,
2020-09-23 08:48:31 +00:00
Index : 0 ,
TxHash : blockGASBounty0 . Hash ( ) ,
} ,
2020-07-03 15:25:18 +00:00
} ,
Address : testchain . PrivateKeyByID ( 0 ) . Address ( ) ,
}
require . Equal ( t , expected . Address , res . Address )
2020-08-07 06:42:44 +00:00
2020-11-24 08:14:25 +00:00
arr := make ( [ ] result . NEP17Transfer , 0 , len ( expected . Sent ) )
2020-08-07 06:42:44 +00:00
for i := range expected . Sent {
2020-09-12 21:12:45 +00:00
for _ , j := range sent {
if i == j {
arr = append ( arr , expected . Sent [ i ] )
break
}
2020-08-07 06:42:44 +00:00
}
}
2020-09-12 21:12:45 +00:00
require . Equal ( t , arr , res . Sent )
2020-08-07 06:42:44 +00:00
arr = arr [ : 0 ]
for i := range expected . Received {
2020-09-12 21:12:45 +00:00
for _ , j := range rcvd {
if i == j {
arr = append ( arr , expected . Received [ i ] )
break
}
2020-08-07 06:42:44 +00:00
}
}
2020-09-12 21:12:45 +00:00
require . Equal ( t , arr , res . Received )
2020-07-03 15:25:18 +00:00
}
2021-10-20 11:32:01 +00:00
2022-03-21 20:36:19 +00:00
func TestEscapeForLog ( t * testing . T ) {
in := "\n\tbad"
require . Equal ( t , "bad" , escapeForLog ( in ) )
}
2021-10-20 11:32:01 +00:00
func BenchmarkHandleIn ( b * testing . B ) {
2022-06-15 18:23:29 +00:00
chain , orc , cfg , logger := getUnitTestChain ( b , false , false , false )
2021-10-20 11:32:01 +00:00
serverConfig := network . NewServerConfig ( cfg )
2022-05-16 03:59:23 +00:00
serverConfig . UserAgent = fmt . Sprintf ( config . UserAgentFormat , "0.98.6-test" )
2021-10-20 11:32:01 +00:00
serverConfig . LogLevel = zapcore . FatalLevel
2022-01-12 21:20:03 +00:00
server , err := network . NewServer ( serverConfig , chain , chain . GetStateSyncModule ( ) , logger )
2021-10-20 11:32:01 +00:00
require . NoError ( b , err )
2022-04-22 07:49:06 +00:00
rpcServer := New ( chain , cfg . ApplicationConfiguration . RPC , server , orc , logger , make ( chan error ) )
2021-10-20 11:32:01 +00:00
defer chain . Close ( )
do := func ( b * testing . B , req [ ] byte ) {
b . ReportAllocs ( )
b . ResetTimer ( )
for i := 0 ; i < b . N ; i ++ {
b . StopTimer ( )
2022-07-07 14:41:01 +00:00
in := new ( params . In )
2021-10-20 11:32:01 +00:00
b . StartTimer ( )
err := json . Unmarshal ( req , in )
if err != nil {
b . FailNow ( )
}
res := rpcServer . handleIn ( in , nil )
if res . Error != nil {
b . FailNow ( )
}
}
b . StopTimer ( )
}
b . Run ( "no extra params" , func ( b * testing . B ) {
do ( b , [ ] byte ( ` { "jsonrpc":"2.0", "method":"validateaddress","params":["Nbb1qkwcwNSBs9pAnrVVrnFbWnbWBk91U2"]} ` ) )
} )
b . Run ( "with extra params" , func ( b * testing . B ) {
do ( b , [ ] byte ( ` { "jsonrpc" : "2.0" , "method" : "validateaddress" , "params" : [ "Nbb1qkwcwNSBs9pAnrVVrnFbWnbWBk91U2" ,
"set" , "of" , "different" , "parameters" , "to" , "see" , "the" , "difference" , "between" , "unmarshalling" , "algorithms" , 1234 , 5678 , 1234567 , 765432 , true , false , null ,
"0x50befd26fdf6e4d957c11e078b24ebce6291456f" , "someMethod" , [ { "type" : "String" , "value" : "50befd26fdf6e4d957c11e078b24ebce6291456f" } ,
{ "type" : "Integer" , "value" : "42" } , { "type" : "Boolean" , "value" : false } ] ] } ` ) )
} )
}