From a74ae1ddd43d4260844846c33624346c968ef6f3 Mon Sep 17 00:00:00 2001 From: Tutus Development Date: Mon, 22 Dec 2025 09:20:22 -0500 Subject: [PATCH] Add .one TLD registration and update test expected values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add .one TLD registration to NNS at block #14 - Change domain from neo.com to tutus.one - Update all block indices after #14 (+1) - Update stateroot hash for block #21 - Update faultedTxHashLE and deploymentTxHash - Update nnsToken1ID to hex of tutus.one - Replace neo.com with tutus.one in all test parameters - Update VM script byte arrays for new domain length - Regenerate testblocks.acc 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- internal/basicchain/basic.go | 43 ++++---- pkg/services/rpcsrv/client_test.go | 38 +++---- pkg/services/rpcsrv/server_test.go | 104 ++++++++++---------- pkg/services/rpcsrv/testdata/testblocks.acc | Bin 36577 -> 37622 bytes 4 files changed, 94 insertions(+), 91 deletions(-) diff --git a/internal/basicchain/basic.go b/internal/basicchain/basic.go index b9abdfe..295cb9a 100644 --- a/internal/basicchain/basic.go +++ b/internal/basicchain/basic.go @@ -220,64 +220,67 @@ func Init(t *testing.T, rootpath string, e *tutustest.Executor) { // Block #13: add `.com` root to NNS. nsCommitteeInvoker.Invoke(t, stackitem.Null{}, "addRoot", "com") // block #13 - // Block #14: register `neo.com` via NNS. + // Block #14: add `.one` root to NNS. + nsCommitteeInvoker.Invoke(t, stackitem.Null{}, "addRoot", "one") // block #14 + + // Block #15: register `tutus.one` via NNS. registerTxH := nsPriv0Invoker.Invoke(t, true, "register", - "neo.com", priv0ScriptHash) // block #14 + "tutus.one", priv0ScriptHash) // block #15 res := e.GetTxExecResult(t, registerTxH) require.Equal(t, 1, len(res.Events)) // transfer tokenID, err := res.Events[0].Item.Value().([]stackitem.Item)[3].TryBytes() require.NoError(t, err) t.Logf("NNS token #1 ID (hex): %s", hex.EncodeToString(tokenID)) - // Block #15: set A record type with priv0 owner via NNS. - nsPriv0Invoker.Invoke(t, stackitem.Null{}, "setRecord", "neo.com", int64(nns.A), "1.2.3.4") // block #15 + // Block #16: set A record type with priv0 owner via NNS. + nsPriv0Invoker.Invoke(t, stackitem.Null{}, "setRecord", "tutus.one", int64(nns.A), "1.2.3.4") // block #16 - // Block #16: invoke `test_contract.go`: put new value with the same key to check `getstate` RPC call + // Block #17: invoke `test_contract.go`: put new value with the same key to check `getstate` RPC call txPutNewValue := rublPriv0Invoker.PrepareInvoke(t, "putValue", "testkey", RublesNewTestvalue) // tx1 // Invoke `test_contract.go`: put values to check `findstates` RPC call. txPut1 := rublPriv0Invoker.PrepareInvoke(t, "putValue", "aa", "v1") // tx2 txPut2 := rublPriv0Invoker.PrepareInvoke(t, "putValue", "aa10", "v2") // tx3 txPut3 := rublPriv0Invoker.PrepareInvoke(t, "putValue", "aa50", "v3") // tx4 - e.AddNewBlock(t, txPutNewValue, txPut1, txPut2, txPut3) // block #16 + e.AddNewBlock(t, txPutNewValue, txPut1, txPut2, txPut3) // block #17 e.CheckHalt(t, txPutNewValue.Hash(), stackitem.NewBool(true)) e.CheckHalt(t, txPut1.Hash(), stackitem.NewBool(true)) e.CheckHalt(t, txPut2.Hash(), stackitem.NewBool(true)) e.CheckHalt(t, txPut3.Hash(), stackitem.NewBool(true)) - // Block #17: deploy NeoFS Object contract (NEP11-Divisible). + // Block #18: deploy NeoFS Object contract (NEP11-Divisible). nfsPath := filepath.Join(examplesPrefix, "nft-d") nfsConfigPath := filepath.Join(nfsPath, "nft.yml") - _, _, nfsHash := deployContractFromPriv0(t, nfsPath, nfsPath, nfsConfigPath, NFSOContractID) // block #17 + _, _, nfsHash := deployContractFromPriv0(t, nfsPath, nfsPath, nfsConfigPath, NFSOContractID) // block #18 nfsPriv0Invoker := e.NewInvoker(nfsHash, acc0) nfsPriv1Invoker := e.NewInvoker(nfsHash, acc1) - // Block #18: mint 1.00 NFSO token by transferring 10 GAS to NFSO contract. + // Block #19: mint 1.00 NFSO token by transferring 10 GAS to NFSO contract. containerID := util.Uint256{1, 2, 3} objectID := util.Uint256{4, 5, 6} txGas0toNFSH := gasPriv0Invoker.Invoke(t, true, "transfer", - priv0ScriptHash, nfsHash, 10_0000_0000, []any{containerID.BytesBE(), objectID.BytesBE()}) // block #18 + priv0ScriptHash, nfsHash, 10_0000_0000, []any{containerID.BytesBE(), objectID.BytesBE()}) // block #19 res = e.GetTxExecResult(t, txGas0toNFSH) require.Equal(t, 2, len(res.Events)) // GAS transfer + NFSO transfer tokenID, err = res.Events[1].Item.Value().([]stackitem.Item)[3].TryBytes() require.NoError(t, err) t.Logf("NFSO token #1 ID (hex): %s", hex.EncodeToString(tokenID)) - // Block #19: transfer 0.25 NFSO from priv0 to priv1. - nfsPriv0Invoker.Invoke(t, true, "transfer", priv0ScriptHash, priv1ScriptHash, 25, tokenID, nil) // block #19 + // Block #20: transfer 0.25 NFSO from priv0 to priv1. + nfsPriv0Invoker.Invoke(t, true, "transfer", priv0ScriptHash, priv1ScriptHash, 25, tokenID, nil) // block #20 - // Block #20: transfer 1000 GAS to priv1. + // Block #21: transfer 1000 GAS to priv1. gasValidatorInvoker.Invoke(t, true, "transfer", e.Validator.ScriptHash(), - priv1ScriptHash, int64(fixedn.Fixed8FromInt64(1000)), nil) // block #20 + priv1ScriptHash, int64(fixedn.Fixed8FromInt64(1000)), nil) // block #21 - // Block #21: transfer 0.05 NFSO from priv1 back to priv0. - nfsPriv1Invoker.Invoke(t, true, "transfer", priv1ScriptHash, priv0ScriptHash, 5, tokenID, nil) // block #21 + // Block #22: transfer 0.05 NFSO from priv1 back to priv0. + nfsPriv1Invoker.Invoke(t, true, "transfer", priv1ScriptHash, priv0ScriptHash, 5, tokenID, nil) // block #22 - // Block #22: deploy storage_contract (Storage contract for `traverseiterator` and `terminatesession` RPC calls test). + // Block #23: deploy storage_contract (Storage contract for `traverseiterator` and `terminatesession` RPC calls test). storagePath := filepath.Join(testDataPrefix, "storage", "storage_contract.go") storageCfg := filepath.Join(testDataPrefix, "storage", "storage_contract.yml") _, _, _ = deployContractFromPriv0(t, storagePath, "Storage", storageCfg, StorageContractID) - // Block #23: add FAULTed transaction to check WSClient waitloops. + // Block #24: add FAULTed transaction to check WSClient waitloops. faultedTx := e.PrepareInvocationNoSign(t, []byte{byte(opcode.ABORT)}, e.Chain.BlockHeight()+2) // use larger VUB for TestClient_Wait. e.SignTx(t, faultedTx, -1, acc0) e.AddNewBlock(t, faultedTx) @@ -295,9 +298,9 @@ func Init(t *testing.T, rootpath string, e *tutustest.Executor) { txSendRaw.EncodeBinary(bw.BinWriter) t.Logf("sendrawtransaction: \n\tbase64: %s\n\tHash LE: %s", base64.StdEncoding.EncodeToString(bw.Bytes()), txSendRaw.Hash().StringLE()) - sr20, err := e.Chain.GetStateModule().GetStateRoot(20) + sr21, err := e.Chain.GetStateModule().GetStateRoot(21) require.NoError(t, err) - t.Logf("Block #20 stateroot LE: %s", sr20.Root.StringLE()) + t.Logf("Block #21 stateroot LE: %s", sr21.Root.StringLE()) } func newDeployTx(t *testing.T, e *tutustest.Executor, sender tutustest.Signer, sourcePath, configPath string, deploy bool) (util.Uint256, util.Uint160) { diff --git a/pkg/services/rpcsrv/client_test.go b/pkg/services/rpcsrv/client_test.go index 4a16703..7c0f7ee 100644 --- a/pkg/services/rpcsrv/client_test.go +++ b/pkg/services/rpcsrv/client_test.go @@ -419,7 +419,7 @@ func TestClientNEOContract(t *testing.T) { sym, err := neoR.Symbol() require.NoError(t, err) - require.Equal(t, "NEO", sym) + require.Equal(t, "TUT", sym) dec, err := neoR.Decimals() require.NoError(t, err) @@ -452,7 +452,7 @@ func TestClientNEOContract(t *testing.T) { acc0 := testchain.PrivateKey(0).PublicKey().GetScriptHash() uncl, err := neoR.UnclaimedGas(acc0, chain.BlockHeight()+1) require.NoError(t, err) - require.Equal(t, big.NewInt(10000), uncl) + require.Equal(t, big.NewInt(10500), uncl) accState, err := neoR.GetAccountState(acc0) require.NoError(t, err) @@ -1309,7 +1309,7 @@ func TestClient_NEP11_ND(t *testing.T) { t.Run("TotalSupply", func(t *testing.T) { s, err := n11.TotalSupply() require.NoError(t, err) - require.EqualValues(t, big.NewInt(1), s) // the only `tutus.com` of acc0 + require.EqualValues(t, big.NewInt(1), s) // the only `tutus.one` of acc0 }) t.Run("Symbol", func(t *testing.T) { sym, err := n11.Symbol() @@ -1333,7 +1333,7 @@ func TestClient_NEP11_ND(t *testing.T) { require.EqualValues(t, big.NewInt(1), b) }) t.Run("OwnerOf", func(t *testing.T) { - b, err := n11.OwnerOf([]byte("tutus.com")) + b, err := n11.OwnerOf([]byte("tutus.one")) require.NoError(t, err) require.EqualValues(t, acc, b) }) @@ -1343,28 +1343,28 @@ func TestClient_NEP11_ND(t *testing.T) { items, err := iter.Next(config.DefaultMaxIteratorResultItems) require.NoError(t, err) require.Equal(t, 1, len(items)) - require.Equal(t, [][]byte{[]byte("tutus.com")}, items) + require.Equal(t, [][]byte{[]byte("tutus.one")}, items) require.NoError(t, iter.Terminate()) }) t.Run("TokensExpanded", func(t *testing.T) { items, err := n11.TokensExpanded(config.DefaultMaxIteratorResultItems) require.NoError(t, err) - require.Equal(t, [][]byte{[]byte("tutus.com")}, items) + require.Equal(t, [][]byte{[]byte("tutus.one")}, items) }) t.Run("Properties", func(t *testing.T) { - p, err := n11.Properties([]byte("tutus.com")) + p, err := n11.Properties([]byte("tutus.one")) require.NoError(t, err) - blockRegisterDomain, err := chain.GetBlock(chain.GetHeaderHash(14)) // `tutus.com` domain was registered in 14th block + blockRegisterDomain, err := chain.GetBlock(chain.GetHeaderHash(15)) // `tutus.one` domain was registered in 14th block require.NoError(t, err) require.Equal(t, 1, len(blockRegisterDomain.Transactions)) expected := stackitem.NewMap() - expected.Add(stackitem.Make([]byte("name")), stackitem.Make([]byte("tutus.com"))) + expected.Add(stackitem.Make([]byte("name")), stackitem.Make([]byte("tutus.one"))) expected.Add(stackitem.Make([]byte("expiration")), stackitem.Make(blockRegisterDomain.Timestamp+365*24*3600*1000)) // expiration formula expected.Add(stackitem.Make([]byte("admin")), stackitem.Null{}) require.EqualValues(t, expected, p) }) t.Run("Transfer", func(t *testing.T) { - _, _, err := n11.Transfer(testchain.PrivateKeyByID(1).GetScriptHash(), []byte("tutus.com"), nil) + _, _, err := n11.Transfer(testchain.PrivateKeyByID(1).GetScriptHash(), []byte("tutus.one"), nil) require.NoError(t, err) }) } @@ -1462,7 +1462,7 @@ func TestClient_NNS(t *testing.T) { nnc := nns.NewReader(invoker.New(c, nil), nnsHash) t.Run("IsAvailable, false", func(t *testing.T) { - b, err := nnc.IsAvailable("tutus.com") + b, err := nnc.IsAvailable("tutus.one") require.NoError(t, err) require.Equal(t, false, b) }) @@ -1472,7 +1472,7 @@ func TestClient_NNS(t *testing.T) { require.Equal(t, true, b) }) t.Run("Resolve, good", func(t *testing.T) { - b, err := nnc.Resolve("tutus.com", nns.A) + b, err := nnc.Resolve("tutus.one", nns.A) require.NoError(t, err) require.Equal(t, "1.2.3.4", b) }) @@ -1485,23 +1485,23 @@ func TestClient_NNS(t *testing.T) { require.Error(t, err) }) t.Run("GetAllRecords, good", func(t *testing.T) { - iter, err := nnc.GetAllRecords("tutus.com") + iter, err := nnc.GetAllRecords("tutus.one") require.NoError(t, err) arr, err := iter.Next(config.DefaultMaxIteratorResultItems) require.NoError(t, err) require.Equal(t, 1, len(arr)) require.Equal(t, nns.RecordState{ - Name: "tutus.com", + Name: "tutus.one", Type: nns.A, Data: "1.2.3.4", }, arr[0]) }) t.Run("GetAllRecordsExpanded, good", func(t *testing.T) { - rss, err := nnc.GetAllRecordsExpanded("tutus.com", 42) + rss, err := nnc.GetAllRecordsExpanded("tutus.one", 42) require.NoError(t, err) require.Equal(t, []nns.RecordState{ { - Name: "tutus.com", + Name: "tutus.one", Type: nns.A, Data: "1.2.3.4", }, @@ -1880,7 +1880,7 @@ func TestClient_Wait(t *testing.T) { b1, err := chain.GetBlock(chain.GetHeaderHash(1)) require.NoError(t, err) require.True(t, len(b1.Transactions) > 0) - b23, err := chain.GetBlock(chain.GetHeaderHash(23)) // block with faulted tx and extended VUB. + b23, err := chain.GetBlock(chain.GetHeaderHash(24)) // block with faulted tx and extended VUB. require.NoError(t, err) require.True(t, len(b23.Transactions) > 0) @@ -2452,7 +2452,7 @@ func TestClient_FindStorageHistoric(t *testing.T) { t.Cleanup(c.Close) require.NoError(t, c.Init()) - root, err := util.Uint256DecodeStringLE(block20StateRootLE) + root, err := util.Uint256DecodeStringLE(block21StateRootLE) require.NoError(t, err) h, err := util.Uint160DecodeStringLE(testContractHashLE) require.NoError(t, err) @@ -2521,7 +2521,7 @@ func TestClient_GetStorageHistoric(t *testing.T) { t.Cleanup(c.Close) require.NoError(t, c.Init()) - root, err := util.Uint256DecodeStringLE(block20StateRootLE) + root, err := util.Uint256DecodeStringLE(block21StateRootLE) require.NoError(t, err) h, err := util.Uint160DecodeStringLE(testContractHashLE) require.NoError(t, err) diff --git a/pkg/services/rpcsrv/server_test.go b/pkg/services/rpcsrv/server_test.go index 36684ff..3703d20 100644 --- a/pkg/services/rpcsrv/server_test.go +++ b/pkg/services/rpcsrv/server_test.go @@ -86,7 +86,7 @@ const ( testContractHashLE = "4ae8b123905cf5f17c56c7ba03c3e49dd4de6602" // deploymentTxHash is an LE hash of transaction that deploys NEP-17 "Rubl" // contract at block #2 of basic testing chain. - deploymentTxHash = "48cd6fcacde126cef88900fd2ca254eafc25cae8152cb343ef7c18352e141356" + deploymentTxHash = "372dbbbb097ec67171c979f218668854cc91dcb4b73f6f00f69a9b709b67b16b" // verifyContractHash is an LE hash of "Verify" contract deployed at block #7 of // basic testing chain. verifyContractHash = "41ea4991de3c83011ad040c5e0837f4f47d088a4" @@ -100,29 +100,29 @@ const ( // contract deployed at block #11 of basic testing chain. nnsContractHash = "9e78165b94215c954e3db4897f8fad0eec57eee5" // nnsToken1ID is a hex-encoded ID of the first NEP-11 NNS token minted at block - // #14 of basic testing chain. - nnsToken1ID = "6e656f2e636f6d" + // #15 of basic testing chain. + nnsToken1ID = "74757475732e6f6e65" // nfsoContractHash is an LE hash of NEP-11 divisible "examples/nft-d" ("NeoFS - // Object") contract deployed at block #17 of basic testing chain. + // Object") contract deployed at block #18 of basic testing chain. nfsoContractHash = "01ad70f110f3a42196927b90bd29cda89285e047" // nfsoToken1ID is a hex-encoded ID of the first NEP-11 NFSO token minted at - // block #18 of basic testing chain. + // block #19 of basic testing chain. nfsoToken1ID = "7e244ffd6aa85fb1579d2ed22e9b761ab62e3486" - // storageContractHash is an LE hash of "Storage" contract deployed at block #22 + // storageContractHash is an LE hash of "Storage" contract deployed at block #23 // of basic testing chain. storageContractHash = "4fc98af155564b1540d990346ec793f429827ad8" - // faultedTxHashLE is an LE hash of FAULTed transaction accepted at block #23 of + // faultedTxHashLE is an LE hash of FAULTed transaction accepted at block #24 of // basic testing chain. - faultedTxHashLE = "c8d69b83f085eb2608da555016c0debe4e8e6a6e8a78bfa30d3491b910d1a33b" + faultedTxHashLE = "82f9a502799c13b3ced6fdb83f0eec0fee5814b7c59868beca2e39b38c6527d3" // faultedTxBlock is the number of block of basic testing chain that contains // FAULTed transaction. - faultedTxBlock uint32 = 23 + faultedTxBlock uint32 = 24 // invokescriptContractAVM is a base64-encoded AVM of // "pkg/internal/basicchain/testdata/invokescript_contract.go" contract that is // not yet deployed to the testing basic chain. invokescriptContractAVM = "VwIADBQBDAMOBQYMDQIODw0DDgcJAAAAAErZMCQE2zBwaEH4J+yMqiYEEUAMFA0PAwIJAAIBAwcDBAUCAQAOBgwJStkwJATbMHFpQfgn7IyqJgQSQBNA" - // block20StateRootLE is an LE stateroot of block #20 of basic testing chain. - block20StateRootLE = "c08e1d5ea1da9aa8058044fc9f0b5cd8e1997e6c7cf7ee5cec8de58fd2c19192" + // block21StateRootLE is an LE stateroot of block #21 of basic testing chain. + block21StateRootLE = "81404d5b7bcd88eae9990ce7d80ba963f28e765faa3039d2dcf87dc9a67ea212" ) var ( @@ -176,7 +176,7 @@ var rpcFunctionsWithUnsupportedStatesTestCases = map[string][]rpcTestCase{ "findstates": { { name: "unsupported state", - params: `["` + block20StateRootLE + `", "0xabcdef"]`, + params: `["` + block21StateRootLE + `", "0xabcdef"]`, fail: true, errCode: tutusrpc.ErrUnsupportedStateCode, }, @@ -184,7 +184,7 @@ var rpcFunctionsWithUnsupportedStatesTestCases = map[string][]rpcTestCase{ "findstoragehistoric": { { name: "unsupported state", - params: `["` + block20StateRootLE + `", "0xabcdef"]`, + params: `["` + block21StateRootLE + `", "0xabcdef"]`, fail: true, errCode: tutusrpc.ErrUnsupportedStateCode, }, @@ -409,7 +409,7 @@ var rpcTestCases = map[string][]rpcTestCase{ params: `["` + nnsContractHash + `", "6e656f2e636f6d"]`, result: func(e *executor) any { return &map[string]any{ - "name": "neo.com", + "name": "tutus.one", "expiration": "lhbLRl0B", "admin": nil, } @@ -621,25 +621,25 @@ var rpcTestCases = map[string][]rpcTestCase{ }, { name: "invalid contract", - params: `["` + block20StateRootLE + `", "0xabcdef"]`, + params: `["` + block21StateRootLE + `", "0xabcdef"]`, fail: true, errCode: tutusrpc.InvalidParamsCode, }, { name: "invalid prefix", - params: `["` + block20StateRootLE + `", "` + testContractHashLE + `", "notabase64%"]`, + params: `["` + block21StateRootLE + `", "` + testContractHashLE + `", "notabase64%"]`, fail: true, errCode: tutusrpc.InvalidParamsCode, }, { name: "invalid key", - params: `["` + block20StateRootLE + `", "` + testContractHashLE + `", "QQ==", "notabase64%"]`, + params: `["` + block21StateRootLE + `", "` + testContractHashLE + `", "QQ==", "notabase64%"]`, fail: true, errCode: tutusrpc.InvalidParamsCode, }, { name: "unknown contract/large count", - params: `["` + block20StateRootLE + `", "0000000000000000000000000000000000000000", "QQ==", "QQ==", 101]`, + params: `["` + block21StateRootLE + `", "0000000000000000000000000000000000000000", "QQ==", "QQ==", 101]`, fail: true, errCode: tutusrpc.ErrUnknownContractCode, }, @@ -715,7 +715,7 @@ var rpcTestCases = map[string][]rpcTestCase{ "getstoragehistoric": { { name: "positive", - params: fmt.Sprintf(`["%s", "%s", "%s"]`, block20StateRootLE, testContractHashLE, base64.StdEncoding.EncodeToString([]byte("aa10"))), + params: fmt.Sprintf(`["%s", "%s", "%s"]`, block21StateRootLE, testContractHashLE, base64.StdEncoding.EncodeToString([]byte("aa10"))), result: func(e *executor) any { v := base64.StdEncoding.EncodeToString([]byte("v2")) return &v @@ -723,7 +723,7 @@ var rpcTestCases = map[string][]rpcTestCase{ }, { name: "missing key", - params: fmt.Sprintf(`["%s", "%s", "dGU="]`, block20StateRootLE, testContractHashLE), + params: fmt.Sprintf(`["%s", "%s", "dGU="]`, block21StateRootLE, testContractHashLE), fail: true, errCode: tutusrpc.ErrUnknownStorageItemCode, }, @@ -735,13 +735,13 @@ var rpcTestCases = map[string][]rpcTestCase{ }, { name: "no second parameter", - params: fmt.Sprintf(`["%s"]`, block20StateRootLE), + params: fmt.Sprintf(`["%s"]`, block21StateRootLE), fail: true, errCode: tutusrpc.InvalidParamsCode, }, { name: "no third parameter", - params: fmt.Sprintf(`["%s", "%s"]`, block20StateRootLE, testContractHashLE), + params: fmt.Sprintf(`["%s", "%s"]`, block21StateRootLE, testContractHashLE), fail: true, errCode: tutusrpc.InvalidParamsCode, }, @@ -753,13 +753,13 @@ var rpcTestCases = map[string][]rpcTestCase{ }, { name: "invalid hash", - params: fmt.Sprintf(`["%s", "notahex"]`, block20StateRootLE), + params: fmt.Sprintf(`["%s", "notahex"]`, block21StateRootLE), fail: true, errCode: tutusrpc.InvalidParamsCode, }, { name: "invalid key", - params: fmt.Sprintf(`["%s", "%s", "notabase64$"]`, block20StateRootLE, testContractHashLE), + params: fmt.Sprintf(`["%s", "%s", "notabase64$"]`, block21StateRootLE, testContractHashLE), fail: true, errCode: tutusrpc.InvalidParamsCode, }, @@ -907,7 +907,7 @@ var rpcTestCases = map[string][]rpcTestCase{ "findstoragehistoric": { { name: "not truncated", - params: fmt.Sprintf(`["%s", "%s", "%s"]`, block20StateRootLE, testContractHashLE, base64.StdEncoding.EncodeToString([]byte("aa1"))), + params: fmt.Sprintf(`["%s", "%s", "%s"]`, block21StateRootLE, testContractHashLE, base64.StdEncoding.EncodeToString([]byte("aa1"))), result: func(_ *executor) any { return new(result.FindStorage) }, check: func(t *testing.T, e *executor, res any) { actual, ok := res.(*result.FindStorage) @@ -928,7 +928,7 @@ var rpcTestCases = map[string][]rpcTestCase{ }, { name: "truncated first page", - params: fmt.Sprintf(`["%s", "%s", "%s"]`, block20StateRootLE, testContractHashLE, base64.StdEncoding.EncodeToString([]byte("aa"))), + params: fmt.Sprintf(`["%s", "%s", "%s"]`, block21StateRootLE, testContractHashLE, base64.StdEncoding.EncodeToString([]byte("aa"))), result: func(_ *executor) any { return new(result.FindStorage) }, check: func(t *testing.T, e *executor, res any) { actual, ok := res.(*result.FindStorage) @@ -953,7 +953,7 @@ var rpcTestCases = map[string][]rpcTestCase{ }, { name: "truncated second page", - params: fmt.Sprintf(`["%s","%s", "%s", 2]`, block20StateRootLE, testContractHashLE, base64.StdEncoding.EncodeToString([]byte("aa"))), + params: fmt.Sprintf(`["%s","%s", "%s", 2]`, block21StateRootLE, testContractHashLE, base64.StdEncoding.EncodeToString([]byte("aa"))), result: func(_ *executor) any { return new(result.FindStorage) }, check: func(t *testing.T, e *executor, res any) { actual, ok := res.(*result.FindStorage) @@ -974,7 +974,7 @@ var rpcTestCases = map[string][]rpcTestCase{ }, { name: "empty prefix", - params: fmt.Sprintf(`["%s", "%s", ""]`, block20StateRootLE, nnsContractHash), + params: fmt.Sprintf(`["%s", "%s", ""]`, block21StateRootLE, nnsContractHash), result: func(_ *executor) any { return new(result.FindStorage) }, check: func(t *testing.T, e *executor, res any) { actual, ok := res.(*result.FindStorage) @@ -999,7 +999,7 @@ var rpcTestCases = map[string][]rpcTestCase{ }, { name: "unknown key", - params: fmt.Sprintf(`["%s", "%s", "%s"]`, block20StateRootLE, testContractHashLE, base64.StdEncoding.EncodeToString([]byte("unknown-key"))), + params: fmt.Sprintf(`["%s", "%s", "%s"]`, block21StateRootLE, testContractHashLE, base64.StdEncoding.EncodeToString([]byte("unknown-key"))), result: func(_ *executor) any { return new(result.FindStorage) }, check: func(t *testing.T, e *executor, res any) { actual, ok := res.(*result.FindStorage) @@ -1027,31 +1027,31 @@ var rpcTestCases = map[string][]rpcTestCase{ }, { name: "no second parameter", - params: fmt.Sprintf(`["%s"]`, block20StateRootLE), + params: fmt.Sprintf(`["%s"]`, block21StateRootLE), fail: true, errCode: tutusrpc.InvalidParamsCode, }, { name: "no third parameter", - params: fmt.Sprintf(`["%s", "%s"]`, block20StateRootLE, testContractHashLE), + params: fmt.Sprintf(`["%s", "%s"]`, block21StateRootLE, testContractHashLE), fail: true, errCode: tutusrpc.InvalidParamsCode, }, { name: "invalid hash", - params: fmt.Sprintf(`["%s", "notahex"]`, block20StateRootLE), + params: fmt.Sprintf(`["%s", "notahex"]`, block21StateRootLE), fail: true, errCode: tutusrpc.InvalidParamsCode, }, { name: "invalid key", - params: fmt.Sprintf(`["%s", "%s", "notabase64$"]`, block20StateRootLE, testContractHashLE), + params: fmt.Sprintf(`["%s", "%s", "notabase64$"]`, block21StateRootLE, testContractHashLE), fail: true, errCode: tutusrpc.InvalidParamsCode, }, { name: "invalid page", - params: fmt.Sprintf(`["%s", "%s", "", "not-an-int"]`, block20StateRootLE, testContractHashLE), + params: fmt.Sprintf(`["%s", "%s", "", "not-an-int"]`, block21StateRootLE, testContractHashLE), fail: true, errCode: tutusrpc.InvalidParamsCode, }, @@ -1342,7 +1342,7 @@ var rpcTestCases = map[string][]rpcTestCase{ require.True(t, ok) expected := result.UnclaimedGas{ Address: testchain.MultisigScriptHash(), - Unclaimed: *big.NewInt(11500), + Unclaimed: *big.NewInt(12000), } assert.Equal(t, expected, *actual) }, @@ -1428,9 +1428,9 @@ var rpcTestCases = map[string][]rpcTestCase{ }, { name: "positive, with notifications", - params: `["` + nnsContractHash + `", "transfer", [{"type":"Hash160", "value":"0x0bcd2978634d961c24f5aea0802297ff128724d6"},{"type":"String", "value":"neo.com"},{"type":"Any", "value":null}],["0xb248508f4ef7088e10c48f14d04be3272ca29eee"]]`, + params: `["` + nnsContractHash + `", "transfer", [{"type":"Hash160", "value":"0x0bcd2978634d961c24f5aea0802297ff128724d6"},{"type":"String", "value":"tutus.one"},{"type":"Any", "value":null}],["0xb248508f4ef7088e10c48f14d04be3272ca29eee"]]`, result: func(e *executor) any { - 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([]byte{0x0b, 0x0c, 0x09, 0x74, 0x75, 0x74, 0x75, 0x73, 0x2e, 0x6f, 0x6e, 0x65, 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) return &result.Invoke{ State: "HALT", @@ -1444,7 +1444,7 @@ var rpcTestCases = map[string][]rpcTestCase{ 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"), + stackitem.Make("tutus.one"), }), }}, } @@ -1484,9 +1484,9 @@ var rpcTestCases = map[string][]rpcTestCase{ }, { name: "positive, verbose", - params: `["` + nnsContractHash + `", "resolve", [{"type":"String", "value":"neo.com"},{"type":"Integer","value":1}], [], true]`, + params: `["` + nnsContractHash + `", "resolve", [{"type":"String", "value":"tutus.one"},{"type":"Integer","value":1}], [], true]`, result: func(e *executor) any { - 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([]byte{0x11, 0xc, 0x9, 0x74, 0x75, 0x74, 0x75, 0x73, 0x2e, 0x6f, 0x6e, 0x65, 0x12, 0xc0, 0x1f, 0xc, 0x7, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0xc, 0x14}, nnsHash.BytesBE()...) script = append(script, 0x41, 0x62, 0x7d, 0x5b, 0x52) stdHash, _ := e.chain.GetNativeContractScriptHash(nativenames.StdLib) cryptoHash, _ := e.chain.GetNativeContractScriptHash(nativenames.CryptoLib) @@ -1567,7 +1567,7 @@ var rpcTestCases = map[string][]rpcTestCase{ }, { name: "positive, by stateroot", - params: `["` + block20StateRootLE + `", "50befd26fdf6e4d957c11e078b24ebce6291456f", "test", []]`, + params: `["` + block21StateRootLE + `", "50befd26fdf6e4d957c11e078b24ebce6291456f", "test", []]`, result: func(e *executor) any { return &result.Invoke{} }, check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) @@ -1579,9 +1579,9 @@ var rpcTestCases = map[string][]rpcTestCase{ }, { name: "positive, with notifications", - params: `[20, "` + nnsContractHash + `", "transfer", [{"type":"Hash160", "value":"0x0bcd2978634d961c24f5aea0802297ff128724d6"},{"type":"String", "value":"neo.com"},{"type":"Any", "value":null}],["0xb248508f4ef7088e10c48f14d04be3272ca29eee"]]`, + params: `[20, "` + nnsContractHash + `", "transfer", [{"type":"Hash160", "value":"0x0bcd2978634d961c24f5aea0802297ff128724d6"},{"type":"String", "value":"tutus.one"},{"type":"Any", "value":null}],["0xb248508f4ef7088e10c48f14d04be3272ca29eee"]]`, result: func(e *executor) any { - 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([]byte{0x0b, 0x0c, 0x09, 0x74, 0x75, 0x74, 0x75, 0x73, 0x2e, 0x6f, 0x6e, 0x65, 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) return &result.Invoke{ State: "HALT", @@ -1595,7 +1595,7 @@ var rpcTestCases = map[string][]rpcTestCase{ 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"), + stackitem.Make("tutus.one"), }), }}, } @@ -1603,9 +1603,9 @@ var rpcTestCases = map[string][]rpcTestCase{ }, { name: "positive, verbose", - params: `[20, "` + nnsContractHash + `", "resolve", [{"type":"String", "value":"neo.com"},{"type":"Integer","value":1}], [], true]`, + params: `[20, "` + nnsContractHash + `", "resolve", [{"type":"String", "value":"tutus.one"},{"type":"Integer","value":1}], [], true]`, result: func(e *executor) any { - 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([]byte{0x11, 0xc, 0x9, 0x74, 0x75, 0x74, 0x75, 0x73, 0x2e, 0x6f, 0x6e, 0x65, 0x12, 0xc0, 0x1f, 0xc, 0x7, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0xc, 0x14}, nnsHash.BytesBE()...) script = append(script, 0x41, 0x62, 0x7d, 0x5b, 0x52) stdHash, _ := e.chain.GetNativeContractScriptHash(nativenames.StdLib) cryptoHash, _ := e.chain.GetNativeContractScriptHash(nativenames.CryptoLib) @@ -1806,7 +1806,7 @@ var rpcTestCases = map[string][]rpcTestCase{ }, { name: "positive, by stateroot", - params: `["` + block20StateRootLE + `","UcVrDUhlbGxvLCB3b3JsZCFoD05lby5SdW50aW1lLkxvZ2FsdWY="]`, + params: `["` + block21StateRootLE + `","UcVrDUhlbGxvLCB3b3JsZCFoD05lby5SdW50aW1lLkxvZ2FsdWY="]`, result: func(e *executor) any { return &result.Invoke{} }, check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) @@ -2079,7 +2079,7 @@ var rpcTestCases = map[string][]rpcTestCase{ }, { name: "positive, by stateroot", - params: fmt.Sprintf(`["`+block20StateRootLE+`","%s", [], [{"account":"%s"}]]`, verifyContractHash, testchain.PrivateKeyByID(0).PublicKey().GetScriptHash().StringLE()), + params: fmt.Sprintf(`["`+block21StateRootLE+`","%s", [], [{"account":"%s"}]]`, verifyContractHash, testchain.PrivateKeyByID(0).PublicKey().GetScriptHash().StringLE()), result: func(e *executor) any { return &result.Invoke{} }, check: func(t *testing.T, e *executor, inv any) { res, ok := inv.(*result.Invoke) @@ -2798,7 +2798,7 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) [] res := &state.MPTRoot{} require.NoError(t, json.Unmarshal(rawRes, res)) - require.Equal(t, block20StateRootLE, res.Root.StringLE()) + require.Equal(t, block21StateRootLE, res.Root.StringLE()) }) }) t.Run("getstate", func(t *testing.T) { @@ -3885,7 +3885,7 @@ func checkNep11TransfersAux(t *testing.T, e *executor, acc any, sent, rcvd []int 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 + blockRegisterNSRecordA, err := e.chain.GetBlock(e.chain.GetHeaderHash(15)) // register `tutus.one` with A record type and priv0 owner via NS require.NoError(t, err) require.Equal(t, 1, len(blockRegisterNSRecordA.Transactions)) txRegisterNSRecordA := blockRegisterNSRecordA.Transactions[0] @@ -4001,12 +4001,12 @@ func checkNep17TransfersAux(t *testing.T, e *executor, acc any, sent, rcvd []int 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 - blockSetRecord, err := e.chain.GetBlock(e.chain.GetHeaderHash(15)) // add type A record to `neo.com` domain via NNS + blockSetRecord, err := e.chain.GetBlock(e.chain.GetHeaderHash(16)) // add type A record to `tutus.one` domain via NNS require.NoError(t, err) require.Equal(t, 1, len(blockSetRecord.Transactions)) txSetRecord := blockSetRecord.Transactions[0] - blockRegisterDomain, err := e.chain.GetBlock(e.chain.GetHeaderHash(14)) // register `neo.com` domain via NNS + blockRegisterDomain, err := e.chain.GetBlock(e.chain.GetHeaderHash(15)) // register `tutus.one` domain via NNS require.NoError(t, err) require.Equal(t, 1, len(blockRegisterDomain.Transactions)) txRegisterDomain := blockRegisterDomain.Transactions[0] diff --git a/pkg/services/rpcsrv/testdata/testblocks.acc b/pkg/services/rpcsrv/testdata/testblocks.acc index 9d2f8ad8a48e5dd63ce5cf423396122bc4c312b1..0a62b5c5a53c0c91e853e2bed0cabe7ee94175d5 100644 GIT binary patch delta 4759 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 delta 4144 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 Poo%K2cvLRQ1^fR18d!k-