From c2b3ee3d8e1b9e7c33062da7811ace6086372064 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 8 Jun 2022 15:17:40 +0300 Subject: [PATCH] core: move basic chain creation into a package of its own This allows to reuse it across different packages. testchain can't be used because of circular dependencies. Init() is not changed except for filepath.Join() use instead of direct string appends which is a better approach anyway. rootpath is required because current directory will change from package to package. --- .gitignore | 1 + internal/basicchain/basic.go | 244 ++++++++++++++++++ .../basicchain}/testdata/invoke/invoke.yml | 0 .../testdata/invoke/invokescript_contract.go | 0 .../basicchain}/testdata/test_contract.go | 0 .../basicchain}/testdata/test_contract.yml | 0 .../testdata/verify/verification_contract.go | 0 .../testdata/verify/verification_contract.yml | 0 .../verification_with_args_contract.go | 0 .../verification_with_args_contract.yml | 0 pkg/core/basic_chain_test.go | 228 +--------------- pkg/core/blockchain_neotest_test.go | 5 +- pkg/core/interop_system_neotest_test.go | 2 +- pkg/core/native/native_test/neo_test.go | 2 +- pkg/core/native_management_test.go | 5 +- pkg/core/stateroot_test.go | 3 +- pkg/core/statesync_test.go | 5 +- 17 files changed, 260 insertions(+), 235 deletions(-) create mode 100644 internal/basicchain/basic.go rename {pkg/rpc/server => internal/basicchain}/testdata/invoke/invoke.yml (100%) rename {pkg/rpc/server => internal/basicchain}/testdata/invoke/invokescript_contract.go (100%) rename {pkg/rpc/server => internal/basicchain}/testdata/test_contract.go (100%) rename {pkg/rpc/server => internal/basicchain}/testdata/test_contract.yml (100%) rename {pkg/rpc/server => internal/basicchain}/testdata/verify/verification_contract.go (100%) rename {pkg/rpc/server => internal/basicchain}/testdata/verify/verification_contract.yml (100%) rename {pkg/rpc/server => internal/basicchain}/testdata/verify_args/verification_with_args_contract.go (100%) rename {pkg/rpc/server => internal/basicchain}/testdata/verify_args/verification_with_args_contract.yml (100%) 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)