diff --git a/.gitignore b/.gitignore index 2a797be7f..88843343e 100644 --- a/.gitignore +++ b/.gitignore @@ -46,6 +46,7 @@ examples/*/*.json # Fuzzing testdata. testdata/ !cli/testdata +!internal/basicchain/testdata !pkg/compiler/testdata !pkg/config/testdata !pkg/consensus/testdata diff --git a/internal/basicchain/basic.go b/internal/basicchain/basic.go new file mode 100644 index 000000000..caf56bf36 --- /dev/null +++ b/internal/basicchain/basic.go @@ -0,0 +1,244 @@ +package basicchain + +import ( + "encoding/base64" + "encoding/hex" + "math/big" + "path" + "path/filepath" + "testing" + + "github.com/nspcc-dev/neo-go/pkg/core/native" + "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" + "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" + "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" + "github.com/nspcc-dev/neo-go/pkg/io" + "github.com/nspcc-dev/neo-go/pkg/neotest" + "github.com/nspcc-dev/neo-go/pkg/rpc/client/nns" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "github.com/nspcc-dev/neo-go/pkg/wallet" + "github.com/stretchr/testify/require" +) + +const neoAmount = 99999000 + +// Init pushes some predefined set of transactions into the given chain, it needs a path to +// the root project directory. +func Init(t *testing.T, rootpath string, e *neotest.Executor) { + if !e.Chain.GetConfig().P2PSigExtensions { + t.Fatal("P2PSigExtensions should be enabled to init basic chain") + } + + var ( + // examplesPrefix is a prefix of the example smart-contracts. + examplesPrefix = filepath.Join(rootpath, "examples") + // testDataPrefix is used to retrieve smart contracts that should be deployed to + // Basic chain. + testDataPrefix = filepath.Join(rootpath, "internal", "basicchain", "testdata") + notaryModulePath = filepath.Join(rootpath, "pkg", "services", "notary") + ) + + gasHash := e.NativeHash(t, nativenames.Gas) + neoHash := e.NativeHash(t, nativenames.Neo) + policyHash := e.NativeHash(t, nativenames.Policy) + notaryHash := e.NativeHash(t, nativenames.Notary) + designationHash := e.NativeHash(t, nativenames.Designation) + t.Logf("native GAS hash: %v", gasHash) + t.Logf("native NEO hash: %v", neoHash) + t.Logf("native Policy hash: %v", policyHash) + t.Logf("native Notary hash: %v", notaryHash) + t.Logf("Block0 hash: %s", e.Chain.GetHeaderHash(0).StringLE()) + + acc0 := e.Validator.(neotest.MultiSigner).Single(2) // priv0 index->order and order->index conversion + priv0ScriptHash := acc0.ScriptHash() + acc1 := e.Validator.(neotest.MultiSigner).Single(0) // priv1 index->order and order->index conversion + priv1ScriptHash := acc1.ScriptHash() + neoValidatorInvoker := e.ValidatorInvoker(neoHash) + gasValidatorInvoker := e.ValidatorInvoker(gasHash) + neoPriv0Invoker := e.NewInvoker(neoHash, acc0) + gasPriv0Invoker := e.NewInvoker(gasHash, acc0) + designateSuperInvoker := e.NewInvoker(designationHash, e.Validator, e.Committee) + + deployContractFromPriv0 := func(t *testing.T, path, contractName string, configPath string, expectedID int32) (util.Uint256, util.Uint256, util.Uint160) { + txDeployHash, cH := newDeployTx(t, e, acc0, path, configPath, true) + b := e.TopBlock(t) + return b.Hash(), txDeployHash, cH + } + + e.CheckGASBalance(t, priv0ScriptHash, big.NewInt(5000_0000)) // gas bounty + + // Block #1: move 1000 GAS and neoAmount NEO to priv0. + txMoveNeo := neoValidatorInvoker.PrepareInvoke(t, "transfer", e.Validator.ScriptHash(), priv0ScriptHash, neoAmount, nil) + txMoveGas := gasValidatorInvoker.PrepareInvoke(t, "transfer", e.Validator.ScriptHash(), priv0ScriptHash, int64(fixedn.Fixed8FromInt64(1000)), nil) + b := e.AddNewBlock(t, txMoveNeo, txMoveGas) + e.CheckHalt(t, txMoveNeo.Hash(), stackitem.Make(true)) + e.CheckHalt(t, txMoveGas.Hash(), stackitem.Make(true)) + t.Logf("Block1 hash: %s", b.Hash().StringLE()) + bw := io.NewBufBinWriter() + b.EncodeBinary(bw.BinWriter) + require.NoError(t, bw.Err) + jsonB, err := b.MarshalJSON() + require.NoError(t, err) + t.Logf("Block1 base64: %s", base64.StdEncoding.EncodeToString(bw.Bytes())) + t.Logf("Block1 JSON: %s", string(jsonB)) + bw.Reset() + b.Header.EncodeBinary(bw.BinWriter) + require.NoError(t, bw.Err) + jsonH, err := b.Header.MarshalJSON() + require.NoError(t, err) + t.Logf("Header1 base64: %s", base64.StdEncoding.EncodeToString(bw.Bytes())) + t.Logf("Header1 JSON: %s", string(jsonH)) + jsonTxMoveNeo, err := txMoveNeo.MarshalJSON() + require.NoError(t, err) + t.Logf("txMoveNeo hash: %s", txMoveNeo.Hash().StringLE()) + t.Logf("txMoveNeo JSON: %s", string(jsonTxMoveNeo)) + t.Logf("txMoveNeo base64: %s", base64.StdEncoding.EncodeToString(txMoveNeo.Bytes())) + t.Logf("txMoveGas hash: %s", txMoveGas.Hash().StringLE()) + + e.EnsureGASBalance(t, priv0ScriptHash, func(balance *big.Int) bool { return balance.Cmp(big.NewInt(1000*native.GASFactor)) >= 0 }) + // info for getblockheader rpc tests + t.Logf("header hash: %s", b.Hash().StringLE()) + buf := io.NewBufBinWriter() + b.Header.EncodeBinary(buf.BinWriter) + t.Logf("header: %s", hex.EncodeToString(buf.Bytes())) + + // Block #2: deploy test_contract (Rubles contract). + cfgPath := filepath.Join(testDataPrefix, "test_contract.yml") + block2H, txDeployH, cHash := deployContractFromPriv0(t, filepath.Join(testDataPrefix, "test_contract.go"), "Rubl", cfgPath, 1) + t.Logf("txDeploy: %s", txDeployH.StringLE()) + t.Logf("Block2 hash: %s", block2H.StringLE()) + + // Block #3: invoke `putValue` method on the test_contract. + rublPriv0Invoker := e.NewInvoker(cHash, acc0) + txInvH := rublPriv0Invoker.Invoke(t, true, "putValue", "testkey", "testvalue") + t.Logf("txInv: %s", txInvH.StringLE()) + + // Block #4: transfer 1000 NEO from priv0 to priv1. + neoPriv0Invoker.Invoke(t, true, "transfer", priv0ScriptHash, priv1ScriptHash, 1000, nil) + + // Block #5: initialize rubles contract and transfer 1000 rubles from the contract to priv0. + initTx := rublPriv0Invoker.PrepareInvoke(t, "init") + transferTx := e.NewUnsignedTx(t, rublPriv0Invoker.Hash, "transfer", cHash, priv0ScriptHash, 1000, nil) + e.SignTx(t, transferTx, 1500_0000, acc0) // Set system fee manually to avoid verification failure. + e.AddNewBlock(t, initTx, transferTx) + e.CheckHalt(t, initTx.Hash(), stackitem.NewBool(true)) + e.CheckHalt(t, transferTx.Hash(), stackitem.Make(true)) + t.Logf("receiveRublesTx: %v", transferTx.Hash().StringLE()) + + // Block #6: transfer 123 rubles from priv0 to priv1 + transferTxH := rublPriv0Invoker.Invoke(t, true, "transfer", priv0ScriptHash, priv1ScriptHash, 123, nil) + t.Logf("sendRublesTx: %v", transferTxH.StringLE()) + + // Block #7: push verification contract into the chain. + verifyPath := filepath.Join(testDataPrefix, "verify", "verification_contract.go") + verifyCfg := filepath.Join(testDataPrefix, "verify", "verification_contract.yml") + _, _, _ = deployContractFromPriv0(t, verifyPath, "Verify", verifyCfg, 2) + + // Block #8: deposit some GAS to notary contract for priv0. + transferTxH = gasPriv0Invoker.Invoke(t, true, "transfer", priv0ScriptHash, notaryHash, 10_0000_0000, []interface{}{priv0ScriptHash, int64(e.Chain.BlockHeight() + 1000)}) + t.Logf("notaryDepositTxPriv0: %v", transferTxH.StringLE()) + + // Block #9: designate new Notary node. + ntr, err := wallet.NewWalletFromFile(path.Join(notaryModulePath, "./testdata/notary1.json")) + require.NoError(t, err) + require.NoError(t, ntr.Accounts[0].Decrypt("one", ntr.Scrypt)) + designateSuperInvoker.Invoke(t, stackitem.Null{}, "designateAsRole", + int64(noderoles.P2PNotary), []interface{}{ntr.Accounts[0].PrivateKey().PublicKey().Bytes()}) + t.Logf("Designated Notary node: %s", hex.EncodeToString(ntr.Accounts[0].PrivateKey().PublicKey().Bytes())) + + // Block #10: push verification contract with arguments into the chain. + verifyPath = filepath.Join(testDataPrefix, "verify_args", "verification_with_args_contract.go") + verifyCfg = filepath.Join(testDataPrefix, "verify_args", "verification_with_args_contract.yml") + _, _, _ = deployContractFromPriv0(t, verifyPath, "VerifyWithArgs", verifyCfg, 3) // block #10 + + // Block #11: push NameService contract into the chain. + nsPath := filepath.Join(examplesPrefix, "nft-nd-nns") + nsConfigPath := filepath.Join(nsPath, "nns.yml") + _, _, nsHash := deployContractFromPriv0(t, nsPath, nsPath, nsConfigPath, 4) // block #11 + nsCommitteeInvoker := e.CommitteeInvoker(nsHash) + nsPriv0Invoker := e.NewInvoker(nsHash, acc0) + + // Block #12: transfer funds to committee for further NS record registration. + gasValidatorInvoker.Invoke(t, true, "transfer", + e.Validator.ScriptHash(), e.Committee.ScriptHash(), 1000_00000000, nil) // block #12 + + // Block #13: add `.com` root to NNS. + nsCommitteeInvoker.Invoke(t, stackitem.Null{}, "addRoot", "com") // block #13 + + // Block #14: register `neo.com` via NNS. + registerTxH := nsPriv0Invoker.Invoke(t, true, "register", + "neo.com", priv0ScriptHash) // block #14 + 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: invoke `test_contract.go`: put new value with the same key to check `getstate` RPC call + txPutNewValue := rublPriv0Invoker.PrepareInvoke(t, "putValue", "testkey", "newtestvalue") // 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.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). + nfsPath := filepath.Join(examplesPrefix, "nft-d") + nfsConfigPath := filepath.Join(nfsPath, "nft.yml") + _, _, nfsHash := deployContractFromPriv0(t, nfsPath, nfsPath, nfsConfigPath, 5) // block #17 + nfsPriv0Invoker := e.NewInvoker(nfsHash, acc0) + nfsPriv1Invoker := e.NewInvoker(nfsHash, acc1) + + // Block #18: 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, []interface{}{containerID.BytesBE(), objectID.BytesBE()}) // block #18 + 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 1000 GAS to priv1. + gasValidatorInvoker.Invoke(t, true, "transfer", e.Validator.ScriptHash(), + priv1ScriptHash, int64(fixedn.Fixed8FromInt64(1000)), nil) // block #20 + + // Block #21: transfer 0.05 NFSO from priv1 back to priv0. + nfsPriv1Invoker.Invoke(t, true, "transfer", priv1ScriptHash, priv0ScriptHash, 5, tokenID, nil) // block #21 + + // Compile contract to test `invokescript` RPC call + invokePath := filepath.Join(testDataPrefix, "invoke", "invokescript_contract.go") + invokeCfg := filepath.Join(testDataPrefix, "invoke", "invoke.yml") + _, _ = newDeployTx(t, e, acc0, invokePath, invokeCfg, false) + + // Prepare some transaction for future submission. + txSendRaw := neoPriv0Invoker.PrepareInvoke(t, "transfer", priv0ScriptHash, priv1ScriptHash, int64(fixedn.Fixed8FromInt64(1000)), nil) + bw.Reset() + 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) + require.NoError(t, err) + t.Logf("Block #20 stateroot LE: %s", sr20.Root.StringLE()) +} + +func newDeployTx(t *testing.T, e *neotest.Executor, sender neotest.Signer, sourcePath, configPath string, deploy bool) (util.Uint256, util.Uint160) { + c := neotest.CompileFile(t, sender.ScriptHash(), sourcePath, configPath) + t.Logf("contract (%s): \n\tHash: %s\n\tAVM: %s", sourcePath, c.Hash.StringLE(), base64.StdEncoding.EncodeToString(c.NEF.Script)) + if deploy { + return e.DeployContractBy(t, sender, c, nil), c.Hash + } + return util.Uint256{}, c.Hash +} diff --git a/pkg/rpc/server/testdata/invoke/invoke.yml b/internal/basicchain/testdata/invoke/invoke.yml similarity index 100% rename from pkg/rpc/server/testdata/invoke/invoke.yml rename to internal/basicchain/testdata/invoke/invoke.yml diff --git a/pkg/rpc/server/testdata/invoke/invokescript_contract.go b/internal/basicchain/testdata/invoke/invokescript_contract.go similarity index 100% rename from pkg/rpc/server/testdata/invoke/invokescript_contract.go rename to internal/basicchain/testdata/invoke/invokescript_contract.go diff --git a/pkg/rpc/server/testdata/test_contract.go b/internal/basicchain/testdata/test_contract.go similarity index 100% rename from pkg/rpc/server/testdata/test_contract.go rename to internal/basicchain/testdata/test_contract.go diff --git a/pkg/rpc/server/testdata/test_contract.yml b/internal/basicchain/testdata/test_contract.yml similarity index 100% rename from pkg/rpc/server/testdata/test_contract.yml rename to internal/basicchain/testdata/test_contract.yml diff --git a/pkg/rpc/server/testdata/verify/verification_contract.go b/internal/basicchain/testdata/verify/verification_contract.go similarity index 100% rename from pkg/rpc/server/testdata/verify/verification_contract.go rename to internal/basicchain/testdata/verify/verification_contract.go diff --git a/pkg/rpc/server/testdata/verify/verification_contract.yml b/internal/basicchain/testdata/verify/verification_contract.yml similarity index 100% rename from pkg/rpc/server/testdata/verify/verification_contract.yml rename to internal/basicchain/testdata/verify/verification_contract.yml diff --git a/pkg/rpc/server/testdata/verify_args/verification_with_args_contract.go b/internal/basicchain/testdata/verify_args/verification_with_args_contract.go similarity index 100% rename from pkg/rpc/server/testdata/verify_args/verification_with_args_contract.go rename to internal/basicchain/testdata/verify_args/verification_with_args_contract.go diff --git a/pkg/rpc/server/testdata/verify_args/verification_with_args_contract.yml b/internal/basicchain/testdata/verify_args/verification_with_args_contract.yml similarity index 100% rename from pkg/rpc/server/testdata/verify_args/verification_with_args_contract.yml rename to internal/basicchain/testdata/verify_args/verification_with_args_contract.yml diff --git a/pkg/core/basic_chain_test.go b/pkg/core/basic_chain_test.go index 5984ef504..ad87db912 100644 --- a/pkg/core/basic_chain_test.go +++ b/pkg/core/basic_chain_test.go @@ -1,34 +1,21 @@ package core_test import ( - "encoding/base64" - "encoding/hex" - "math/big" "os" - "path" "path/filepath" "testing" "time" + "github.com/nspcc-dev/neo-go/internal/basicchain" "github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/core/chaindump" - "github.com/nspcc-dev/neo-go/pkg/core/native" - "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" - "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" - "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/neotest" "github.com/nspcc-dev/neo-go/pkg/neotest/chain" - "github.com/nspcc-dev/neo-go/pkg/rpc/client/nns" - "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" - "github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/stretchr/testify/require" ) const ( - // examplesPrefix is a prefix of the example smart-contracts. - examplesPrefix = "../../examples/" // basicChainPrefix is a prefix used to store Basic chain .acc file for tests. // It is also used to retrieve smart contracts that should be deployed to // Basic chain. @@ -56,7 +43,7 @@ func TestCreateBasicChain(t *testing.T) { }) e := neotest.NewExecutor(t, bc, validators, committee) - initBasicChain(t, e) + basicchain.Init(t, "../../", e) if saveChain { outStream, err := os.Create(basicChainPrefix + "testblocks.acc") @@ -73,214 +60,3 @@ func TestCreateBasicChain(t *testing.T) { require.False(t, saveChain) } - -func initBasicChain(t *testing.T, e *neotest.Executor) { - if !e.Chain.GetConfig().P2PSigExtensions { - t.Fatal("P2PSigExtensions should be enabled to init basic chain") - } - - const neoAmount = 99999000 - - gasHash := e.NativeHash(t, nativenames.Gas) - neoHash := e.NativeHash(t, nativenames.Neo) - policyHash := e.NativeHash(t, nativenames.Policy) - notaryHash := e.NativeHash(t, nativenames.Notary) - designationHash := e.NativeHash(t, nativenames.Designation) - t.Logf("native GAS hash: %v", gasHash) - t.Logf("native NEO hash: %v", neoHash) - t.Logf("native Policy hash: %v", policyHash) - t.Logf("native Notary hash: %v", notaryHash) - t.Logf("Block0 hash: %s", e.Chain.GetHeaderHash(0).StringLE()) - - acc0 := e.Validator.(neotest.MultiSigner).Single(2) // priv0 index->order and order->index conversion - priv0ScriptHash := acc0.ScriptHash() - acc1 := e.Validator.(neotest.MultiSigner).Single(0) // priv1 index->order and order->index conversion - priv1ScriptHash := acc1.ScriptHash() - neoValidatorInvoker := e.ValidatorInvoker(neoHash) - gasValidatorInvoker := e.ValidatorInvoker(gasHash) - neoPriv0Invoker := e.NewInvoker(neoHash, acc0) - gasPriv0Invoker := e.NewInvoker(gasHash, acc0) - designateSuperInvoker := e.NewInvoker(designationHash, e.Validator, e.Committee) - - deployContractFromPriv0 := func(t *testing.T, path, contractName string, configPath string, expectedID int32) (util.Uint256, util.Uint256, util.Uint160) { - txDeployHash, cH := newDeployTx(t, e, acc0, path, configPath, true) - b := e.TopBlock(t) - return b.Hash(), txDeployHash, cH - } - - e.CheckGASBalance(t, priv0ScriptHash, big.NewInt(5000_0000)) // gas bounty - - // Block #1: move 1000 GAS and neoAmount NEO to priv0. - txMoveNeo := neoValidatorInvoker.PrepareInvoke(t, "transfer", e.Validator.ScriptHash(), priv0ScriptHash, neoAmount, nil) - txMoveGas := gasValidatorInvoker.PrepareInvoke(t, "transfer", e.Validator.ScriptHash(), priv0ScriptHash, int64(fixedn.Fixed8FromInt64(1000)), nil) - b := e.AddNewBlock(t, txMoveNeo, txMoveGas) - e.CheckHalt(t, txMoveNeo.Hash(), stackitem.Make(true)) - e.CheckHalt(t, txMoveGas.Hash(), stackitem.Make(true)) - t.Logf("Block1 hash: %s", b.Hash().StringLE()) - bw := io.NewBufBinWriter() - b.EncodeBinary(bw.BinWriter) - require.NoError(t, bw.Err) - jsonB, err := b.MarshalJSON() - require.NoError(t, err) - t.Logf("Block1 base64: %s", base64.StdEncoding.EncodeToString(bw.Bytes())) - t.Logf("Block1 JSON: %s", string(jsonB)) - bw.Reset() - b.Header.EncodeBinary(bw.BinWriter) - require.NoError(t, bw.Err) - jsonH, err := b.Header.MarshalJSON() - require.NoError(t, err) - t.Logf("Header1 base64: %s", base64.StdEncoding.EncodeToString(bw.Bytes())) - t.Logf("Header1 JSON: %s", string(jsonH)) - jsonTxMoveNeo, err := txMoveNeo.MarshalJSON() - require.NoError(t, err) - t.Logf("txMoveNeo hash: %s", txMoveNeo.Hash().StringLE()) - t.Logf("txMoveNeo JSON: %s", string(jsonTxMoveNeo)) - t.Logf("txMoveNeo base64: %s", base64.StdEncoding.EncodeToString(txMoveNeo.Bytes())) - t.Logf("txMoveGas hash: %s", txMoveGas.Hash().StringLE()) - - e.EnsureGASBalance(t, priv0ScriptHash, func(balance *big.Int) bool { return balance.Cmp(big.NewInt(1000*native.GASFactor)) >= 0 }) - // info for getblockheader rpc tests - t.Logf("header hash: %s", b.Hash().StringLE()) - buf := io.NewBufBinWriter() - b.Header.EncodeBinary(buf.BinWriter) - t.Logf("header: %s", hex.EncodeToString(buf.Bytes())) - - // Block #2: deploy test_contract (Rubles contract). - cfgPath := basicChainPrefix + "test_contract.yml" - block2H, txDeployH, cHash := deployContractFromPriv0(t, basicChainPrefix+"test_contract.go", "Rubl", cfgPath, 1) - t.Logf("txDeploy: %s", txDeployH.StringLE()) - t.Logf("Block2 hash: %s", block2H.StringLE()) - - // Block #3: invoke `putValue` method on the test_contract. - rublPriv0Invoker := e.NewInvoker(cHash, acc0) - txInvH := rublPriv0Invoker.Invoke(t, true, "putValue", "testkey", "testvalue") - t.Logf("txInv: %s", txInvH.StringLE()) - - // Block #4: transfer 1000 NEO from priv0 to priv1. - neoPriv0Invoker.Invoke(t, true, "transfer", priv0ScriptHash, priv1ScriptHash, 1000, nil) - - // Block #5: initialize rubles contract and transfer 1000 rubles from the contract to priv0. - initTx := rublPriv0Invoker.PrepareInvoke(t, "init") - transferTx := e.NewUnsignedTx(t, rublPriv0Invoker.Hash, "transfer", cHash, priv0ScriptHash, 1000, nil) - e.SignTx(t, transferTx, 1500_0000, acc0) // Set system fee manually to avoid verification failure. - e.AddNewBlock(t, initTx, transferTx) - e.CheckHalt(t, initTx.Hash(), stackitem.NewBool(true)) - e.CheckHalt(t, transferTx.Hash(), stackitem.Make(true)) - t.Logf("receiveRublesTx: %v", transferTx.Hash().StringLE()) - - // Block #6: transfer 123 rubles from priv0 to priv1 - transferTxH := rublPriv0Invoker.Invoke(t, true, "transfer", priv0ScriptHash, priv1ScriptHash, 123, nil) - t.Logf("sendRublesTx: %v", transferTxH.StringLE()) - - // Block #7: push verification contract into the chain. - verifyPath := filepath.Join(basicChainPrefix, "verify", "verification_contract.go") - verifyCfg := filepath.Join(basicChainPrefix, "verify", "verification_contract.yml") - _, _, _ = deployContractFromPriv0(t, verifyPath, "Verify", verifyCfg, 2) - - // Block #8: deposit some GAS to notary contract for priv0. - transferTxH = gasPriv0Invoker.Invoke(t, true, "transfer", priv0ScriptHash, notaryHash, 10_0000_0000, []interface{}{priv0ScriptHash, int64(e.Chain.BlockHeight() + 1000)}) - t.Logf("notaryDepositTxPriv0: %v", transferTxH.StringLE()) - - // Block #9: designate new Notary node. - ntr, err := wallet.NewWalletFromFile(path.Join(notaryModulePath, "./testdata/notary1.json")) - require.NoError(t, err) - require.NoError(t, ntr.Accounts[0].Decrypt("one", ntr.Scrypt)) - designateSuperInvoker.Invoke(t, stackitem.Null{}, "designateAsRole", - int64(noderoles.P2PNotary), []interface{}{ntr.Accounts[0].PrivateKey().PublicKey().Bytes()}) - t.Logf("Designated Notary node: %s", hex.EncodeToString(ntr.Accounts[0].PrivateKey().PublicKey().Bytes())) - - // Block #10: push verification contract with arguments into the chain. - verifyPath = filepath.Join(basicChainPrefix, "verify_args", "verification_with_args_contract.go") - verifyCfg = filepath.Join(basicChainPrefix, "verify_args", "verification_with_args_contract.yml") - _, _, _ = deployContractFromPriv0(t, verifyPath, "VerifyWithArgs", verifyCfg, 3) // block #10 - - // Block #11: push NameService contract into the chain. - nsPath := examplesPrefix + "nft-nd-nns/" - nsConfigPath := nsPath + "nns.yml" - _, _, nsHash := deployContractFromPriv0(t, nsPath, nsPath, nsConfigPath, 4) // block #11 - nsCommitteeInvoker := e.CommitteeInvoker(nsHash) - nsPriv0Invoker := e.NewInvoker(nsHash, acc0) - - // Block #12: transfer funds to committee for further NS record registration. - gasValidatorInvoker.Invoke(t, true, "transfer", - e.Validator.ScriptHash(), e.Committee.ScriptHash(), 1000_00000000, nil) // block #12 - - // Block #13: add `.com` root to NNS. - nsCommitteeInvoker.Invoke(t, stackitem.Null{}, "addRoot", "com") // block #13 - - // Block #14: register `neo.com` via NNS. - registerTxH := nsPriv0Invoker.Invoke(t, true, "register", - "neo.com", priv0ScriptHash) // block #14 - 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: invoke `test_contract.go`: put new value with the same key to check `getstate` RPC call - txPutNewValue := rublPriv0Invoker.PrepareInvoke(t, "putValue", "testkey", "newtestvalue") // 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.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). - nfsPath := examplesPrefix + "nft-d/" - nfsConfigPath := nfsPath + "nft.yml" - _, _, nfsHash := deployContractFromPriv0(t, nfsPath, nfsPath, nfsConfigPath, 5) // block #17 - nfsPriv0Invoker := e.NewInvoker(nfsHash, acc0) - nfsPriv1Invoker := e.NewInvoker(nfsHash, acc1) - - // Block #18: 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, []interface{}{containerID.BytesBE(), objectID.BytesBE()}) // block #18 - 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 1000 GAS to priv1. - gasValidatorInvoker.Invoke(t, true, "transfer", e.Validator.ScriptHash(), - priv1ScriptHash, int64(fixedn.Fixed8FromInt64(1000)), nil) // block #20 - - // Block #21: transfer 0.05 NFSO from priv1 back to priv0. - nfsPriv1Invoker.Invoke(t, true, "transfer", priv1ScriptHash, priv0ScriptHash, 5, tokenID, nil) // block #21 - - // Compile contract to test `invokescript` RPC call - invokePath := filepath.Join(basicChainPrefix, "invoke", "invokescript_contract.go") - invokeCfg := filepath.Join(basicChainPrefix, "invoke", "invoke.yml") - _, _ = newDeployTx(t, e, acc0, invokePath, invokeCfg, false) - - // Prepare some transaction for future submission. - txSendRaw := neoPriv0Invoker.PrepareInvoke(t, "transfer", priv0ScriptHash, priv1ScriptHash, int64(fixedn.Fixed8FromInt64(1000)), nil) - bw.Reset() - 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) - require.NoError(t, err) - t.Logf("Block #20 stateroot LE: %s", sr20.Root.StringLE()) -} - -func newDeployTx(t *testing.T, e *neotest.Executor, sender neotest.Signer, sourcePath, configPath string, deploy bool) (util.Uint256, util.Uint160) { - c := neotest.CompileFile(t, sender.ScriptHash(), sourcePath, configPath) - t.Logf("contract (%s): \n\tHash: %s\n\tAVM: %s", sourcePath, c.Hash.StringLE(), base64.StdEncoding.EncodeToString(c.NEF.Script)) - if deploy { - return e.DeployContractBy(t, sender, c, nil), c.Hash - } - return util.Uint256{}, c.Hash -} diff --git a/pkg/core/blockchain_neotest_test.go b/pkg/core/blockchain_neotest_test.go index 91a25d12f..4049e3c51 100644 --- a/pkg/core/blockchain_neotest_test.go +++ b/pkg/core/blockchain_neotest_test.go @@ -10,6 +10,7 @@ import ( "testing" "time" + "github.com/nspcc-dev/neo-go/internal/basicchain" "github.com/nspcc-dev/neo-go/internal/contracts" "github.com/nspcc-dev/neo-go/internal/random" "github.com/nspcc-dev/neo-go/pkg/compiler" @@ -81,7 +82,7 @@ func testDumpAndRestore(t *testing.T, dumpF, restoreF func(c *config.ProtocolCon bc, validators, committee := chain.NewMultiWithCustomConfig(t, dumpF) e := neotest.NewExecutor(t, bc, validators, committee) - initBasicChain(t, e) + basicchain.Init(t, "../../", e) require.True(t, bc.BlockHeight() > 5) // ensure that test is valid w := io.NewBufBinWriter() @@ -147,7 +148,7 @@ func TestBlockchain_StartFromExistingDB(t *testing.T) { require.NoError(t, err) go bc.Run() e := neotest.NewExecutor(t, bc, validators, committee) - initBasicChain(t, e) + basicchain.Init(t, "../../", e) require.True(t, bc.BlockHeight() > 5, "ensure that basic chain is correctly initialised") // Information for further tests. diff --git a/pkg/core/interop_system_neotest_test.go b/pkg/core/interop_system_neotest_test.go index 7fa7ba060..99fcee560 100644 --- a/pkg/core/interop_system_neotest_test.go +++ b/pkg/core/interop_system_neotest_test.go @@ -263,7 +263,7 @@ func TestSystemRuntimeBurnGas(t *testing.T) { func TestSystemContractCreateAccount_Hardfork(t *testing.T) { bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.ProtocolConfiguration) { - c.P2PSigExtensions = true // `initBasicChain` requires Notary enabled + c.P2PSigExtensions = true // `basicchain.Init` requires Notary enabled c.Hardforks = map[string]uint32{ config.HFAspidochelone.String(): 2, } diff --git a/pkg/core/native/native_test/neo_test.go b/pkg/core/native/native_test/neo_test.go index 26eb69085..6d8ee3275 100644 --- a/pkg/core/native/native_test/neo_test.go +++ b/pkg/core/native/native_test/neo_test.go @@ -279,7 +279,7 @@ func TestNEO_RecursiveGASMint(t *testing.T) { e := neoCommitteeInvoker.Executor gasValidatorInvoker := e.ValidatorInvoker(e.NativeHash(t, nativenames.Gas)) - c := neotest.CompileFile(t, e.Validator.ScriptHash(), "../../../rpc/server/testdata/test_contract.go", "../../../rpc/server/testdata/test_contract.yml") + c := neotest.CompileFile(t, e.Validator.ScriptHash(), "../../../../internal/basicchain/testdata/test_contract.go", "../../../../internal/basicchain/testdata/test_contract.yml") e.DeployContract(t, c, nil) gasValidatorInvoker.Invoke(t, true, "transfer", e.Validator.ScriptHash(), c.Hash, int64(2_0000_0000), nil) diff --git a/pkg/core/native_management_test.go b/pkg/core/native_management_test.go index e38a8cf96..e02e022dd 100644 --- a/pkg/core/native_management_test.go +++ b/pkg/core/native_management_test.go @@ -3,6 +3,7 @@ package core_test import ( "testing" + "github.com/nspcc-dev/neo-go/internal/basicchain" "github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" "github.com/nspcc-dev/neo-go/pkg/neotest" @@ -22,10 +23,10 @@ func TestManagement_GetNEP17Contracts(t *testing.T) { t.Run("basic chain", func(t *testing.T) { bc, validators, committee := chain.NewMultiWithCustomConfig(t, func(c *config.ProtocolConfiguration) { - c.P2PSigExtensions = true // `initBasicChain` requires Notary enabled + c.P2PSigExtensions = true // `basicchain.Init` requires Notary enabled }) e := neotest.NewExecutor(t, bc, validators, committee) - initBasicChain(t, e) + basicchain.Init(t, "../../", e) require.ElementsMatch(t, []util.Uint160{e.NativeHash(t, nativenames.Neo), e.NativeHash(t, nativenames.Gas), e.ContractHash(t, 1)}, bc.GetNEP17Contracts()) diff --git a/pkg/core/stateroot_test.go b/pkg/core/stateroot_test.go index 86df6c8b5..f0ed8d1d5 100644 --- a/pkg/core/stateroot_test.go +++ b/pkg/core/stateroot_test.go @@ -8,6 +8,7 @@ import ( "testing" "time" + "github.com/nspcc-dev/neo-go/internal/basicchain" "github.com/nspcc-dev/neo-go/internal/testserdes" "github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/config/netmode" @@ -302,7 +303,7 @@ func TestStateroot_GetLatestStateHeight(t *testing.T) { c.P2PSigExtensions = true }) e := neotest.NewExecutor(t, bc, validators, committee) - initBasicChain(t, e) + basicchain.Init(t, "../../", e) m := bc.GetStateModule() for i := uint32(0); i < bc.BlockHeight(); i++ { diff --git a/pkg/core/statesync_test.go b/pkg/core/statesync_test.go index 4162c921b..326c40a58 100644 --- a/pkg/core/statesync_test.go +++ b/pkg/core/statesync_test.go @@ -3,6 +3,7 @@ package core_test import ( "testing" + "github.com/nspcc-dev/neo-go/internal/basicchain" "github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/mpt" @@ -291,13 +292,13 @@ func TestStateSyncModule_RestoreBasicChain(t *testing.T) { c.P2PStateExchangeExtensions = true c.StateSyncInterval = stateSyncInterval c.MaxTraceableBlocks = maxTraceable - c.P2PSigExtensions = true // `initBasicChain` assumes Notary is enabled. + c.P2PSigExtensions = true // `basicchain.Init` assumes Notary is enabled. } bcSpoutStore := storage.NewMemoryStore() bcSpout, validators, committee := chain.NewMultiWithCustomConfigAndStore(t, spoutCfg, bcSpoutStore, false) go bcSpout.Run() // Will close it manually at the end. e := neotest.NewExecutor(t, bcSpout, validators, committee) - initBasicChain(t, e) + basicchain.Init(t, "../../", e) // make spout chain higher that latest state sync point (add several blocks up to stateSyncPoint+2) e.AddNewBlock(t)