diff --git a/cmd/node/main.go b/cmd/node/main.go index 1e666436696..2007ff4f06f 100644 --- a/cmd/node/main.go +++ b/cmd/node/main.go @@ -37,14 +37,11 @@ import ( "github.com/ElrondNetwork/elrond-go/node" "github.com/ElrondNetwork/elrond-go/node/external" "github.com/ElrondNetwork/elrond-go/ntp" - factoryVM "github.com/ElrondNetwork/elrond-go/process/factory" + "github.com/ElrondNetwork/elrond-go/process/factory/shard" "github.com/ElrondNetwork/elrond-go/process/smartContract" - "github.com/ElrondNetwork/elrond-go/process/smartContract/hooks" "github.com/ElrondNetwork/elrond-go/sharding" "github.com/ElrondNetwork/elrond-go/statusHandler" factoryViews "github.com/ElrondNetwork/elrond-go/statusHandler/factory" - vmcommon "github.com/ElrondNetwork/elrond-vm-common" - "github.com/ElrondNetwork/elrond-vm/iele/elrond/node/endpoint" "github.com/google/gops/agent" "github.com/urfave/cli" ) @@ -639,19 +636,15 @@ func startNode(ctx *cli.Context, log *logger.Logger, version string) error { return err } - vmAccountsDB, err := hooks.NewVMAccountsDB( + apiResolver, err := createApiResolver( stateComponents.AccountsAdapter, stateComponents.AddressConverter, + statusMetrics, ) if err != nil { return err } - apiResolver, err := createApiResolver(vmAccountsDB, statusMetrics) - if err != nil { - return err - } - err = startStatusPolling( currentNode.GetAppStatusHandler(), generalConfig.GeneralSettings.StatusPollingIntervalSec, @@ -1212,12 +1205,18 @@ func startStatisticsMonitor(file *os.File, config config.ResourceStatsConfig, lo return nil } -func createApiResolver(vmAccountsDB vmcommon.BlockchainHook, statusMetrics external.StatusMetricsHandler) (facade.ApiResolver, error) { - //TODO replace this with a vm factory - cryptoHook := hooks.NewVMCryptoHook() - ieleVM := endpoint.NewElrondIeleVM(factoryVM.IELEVirtualMachine, endpoint.ElrondTestnet, vmAccountsDB, cryptoHook) +func createApiResolver(accounts state.AccountsAdapter, converter state.AddressConverter, statusMetrics external.StatusMetricsHandler) (facade.ApiResolver, error) { + vmFactory, err := shard.NewVMContainerFactory(accounts, converter) + if err != nil { + return nil, err + } + + vmContainer, err := vmFactory.Create() + if err != nil { + return nil, err + } - scDataGetter, err := smartContract.NewSCDataGetter(ieleVM) + scDataGetter, err := smartContract.NewSCDataGetter(vmContainer) if err != nil { return nil, err } diff --git a/go.mod b/go.mod index da761e66e69..6a484343afc 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.12 require ( github.com/360EntSecGroup-Skylar/excelize v1.4.1 + github.com/ElrondNetwork/arwen-wasm-vm v0.0.8 github.com/ElrondNetwork/concurrent-map v0.1.2 github.com/ElrondNetwork/elrond-vm v0.0.19 github.com/ElrondNetwork/elrond-vm-common v0.0.8 diff --git a/go.sum b/go.sum index 5f960aa4f05..99180bebba4 100644 --- a/go.sum +++ b/go.sum @@ -7,6 +7,8 @@ github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9 h1:HD8gA2tkBy github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/ElrondNetwork/arwen-wasm-vm v0.0.8 h1:Va5y2E3SD+SF+cOWxTpT6MJYNmrd+LE1qUs8VdEzXvU= +github.com/ElrondNetwork/arwen-wasm-vm v0.0.8/go.mod h1:uGYpcjg8Oa3tkdS7Yc9sHUgEIPSnmHoDFdodgiZ0iyU= github.com/ElrondNetwork/concurrent-map v0.1.2 h1:mr2sVF2IPDsJO8DNGzCUiNQOJcadHuIRVZn+QFnCBlE= github.com/ElrondNetwork/concurrent-map v0.1.2/go.mod h1:3XwSwn4JHI0lrKxWLZvtp53Emr8BXYTmNQGwcukHJEE= github.com/ElrondNetwork/elrond-vm v0.0.19 h1:9E8spYj9K1DHdF0Osgj1dZUJfKhfBiLBx1xWWfE/HAM= @@ -16,6 +18,8 @@ github.com/ElrondNetwork/elrond-vm-common v0.0.7/go.mod h1:VqCCN0cX0e4D/KDc7MGNV github.com/ElrondNetwork/elrond-vm-common v0.0.8 h1:YyJ55gYeCL3e2v+06ZLJrwzkOXPvuSvLm7pBL1qD0Rk= github.com/ElrondNetwork/elrond-vm-common v0.0.8/go.mod h1:VqCCN0cX0e4D/KDc7MGNV9ElrOsfnjuJnGvcODVjzbk= github.com/ElrondNetwork/elrond-vm-util v0.0.3/go.mod h1:/gz1QHx7ndQnjQDAEEhpiiaezbyl/woTI6apOsWrN10= +github.com/ElrondNetwork/go-ext-wasm v0.0.0-20190923181727-2aed5e4238f5 h1:XUFbny/dhk55M2RCLTrwCFjcUUwufPvrejxN3The5Sg= +github.com/ElrondNetwork/go-ext-wasm v0.0.0-20190923181727-2aed5e4238f5/go.mod h1:+OQYLOaYAxbnkA5WWbiya03JsQng7wg8jKwlJNyQb68= github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= github.com/StackExchange/wmi v0.0.0-20170410192909-ea383cf3ba6e h1:IHXQQIpxASe3m0Jtcd3XongL+lxHNd5nUmvHxJARUmg= github.com/StackExchange/wmi v0.0.0-20170410192909-ea383cf3ba6e/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= @@ -476,8 +480,6 @@ golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443 h1:IcSOAf4PyMp3U3XbIEj1/xJ2BjNN2jWv7JoyOsMxXUU= golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 h1:Gv7RPwsi3eZ2Fgewe3CBsuOebPwO27PoXzRpJPsvSSM= diff --git a/integrationTests/multiShard/block/executingMiniblocksSc_test.go b/integrationTests/multiShard/block/executingMiniblocksSc_test.go index 826e409ee66..a4d28b4f9c0 100644 --- a/integrationTests/multiShard/block/executingMiniblocksSc_test.go +++ b/integrationTests/multiShard/block/executingMiniblocksSc_test.go @@ -10,6 +10,7 @@ import ( "time" "github.com/ElrondNetwork/elrond-go/integrationTests" + "github.com/ElrondNetwork/elrond-go/process/factory" "github.com/ElrondNetwork/elrond-go/sharding" "github.com/stretchr/testify/assert" ) @@ -39,7 +40,6 @@ func TestProcessWithScTxsTopUpAndWithdrawOnlyProposers(t *testing.T) { nodeShard0 := integrationTests.NewTestProcessorNode(maxShards, 0, 0, advertiserAddr) nodeShard1 := integrationTests.NewTestProcessorNode(maxShards, 1, 1, advertiserAddr) hardCodedSk, _ := hex.DecodeString("5561d28b0d89fa425bbbf9e49a018b5d1e4a462c03d2efce60faf9ddece2af06") - hardCodedScResultingAddress, _ := hex.DecodeString("000000000000000001006c560111a94e434413c1cdaafbc3e1348947d1d5b3a1") nodeShard1.LoadTxSignSkBytes(hardCodedSk) nodeMeta := integrationTests.NewTestProcessorNode(maxShards, sharding.MetachainShardId, 0, advertiserAddr) @@ -73,6 +73,11 @@ func TestProcessWithScTxsTopUpAndWithdrawOnlyProposers(t *testing.T) { withdrawValue := big.NewInt(10) integrationTests.MintAllNodes(nodes, initialVal) + hardCodedScResultingAddress, _ := nodeShard1.BlockchainHook.NewAddress( + nodes[idxNodeShard1].OwnAccount.Address.Bytes(), + nodes[idxNodeShard1].OwnAccount.Nonce, + factory.IELEVirtualMachine, + ) integrationTests.DeployScTx(nodes, idxNodeShard1, string(scCode)) integrationTests.ProposeBlock(nodes, idxProposers, round, nonce) diff --git a/integrationTests/testInitializer.go b/integrationTests/testInitializer.go index f2cc989a9ce..b6762e696e5 100644 --- a/integrationTests/testInitializer.go +++ b/integrationTests/testInitializer.go @@ -39,14 +39,13 @@ import ( "github.com/ElrondNetwork/elrond-go/p2p/loadBalancer" "github.com/ElrondNetwork/elrond-go/process" procFactory "github.com/ElrondNetwork/elrond-go/process/factory" + "github.com/ElrondNetwork/elrond-go/process/factory/shard" "github.com/ElrondNetwork/elrond-go/process/smartContract/hooks" txProc "github.com/ElrondNetwork/elrond-go/process/transaction" "github.com/ElrondNetwork/elrond-go/sharding" "github.com/ElrondNetwork/elrond-go/storage" "github.com/ElrondNetwork/elrond-go/storage/memorydb" "github.com/ElrondNetwork/elrond-go/storage/storageUnit" - vmcommon "github.com/ElrondNetwork/elrond-vm-common" - "github.com/ElrondNetwork/elrond-vm/iele/elrond/node/endpoint" "github.com/btcsuite/btcd/btcec" libp2pCrypto "github.com/libp2p/go-libp2p-core/crypto" "github.com/pkg/errors" @@ -278,14 +277,13 @@ func CreateGenesisMetaBlock() *dataBlock.MetaBlock { } // CreateIeleVMAndBlockchainHook creates a new instance of a iele VM -func CreateIeleVMAndBlockchainHook( +func CreateVMContainerAndBlockchainHook( accnts state.AccountsAdapter, -) (vmcommon.VMExecutionHandler, *hooks.VMAccountsDB) { - blockChainHook, _ := hooks.NewVMAccountsDB(accnts, TestAddressConverter) - cryptoHook := hooks.NewVMCryptoHook() - vm := endpoint.NewElrondIeleVM(procFactory.IELEVirtualMachine, endpoint.ElrondTestnet, blockChainHook, cryptoHook) +) (process.VirtualMachinesContainer, *hooks.VMAccountsDB) { + vmFactory, _ := shard.NewVMContainerFactory(accnts, TestAddressConverter) + vmContainer, _ := vmFactory.Create() - return vm, blockChainHook + return vmContainer, vmFactory.VMAccountsDB() } // CreateAddressFromAddrBytes creates an address container object from address bytes provided diff --git a/integrationTests/testProcessorNode.go b/integrationTests/testProcessorNode.go index 1a0fe3fdb3a..d7e136d972f 100644 --- a/integrationTests/testProcessorNode.go +++ b/integrationTests/testProcessorNode.go @@ -38,7 +38,6 @@ import ( "github.com/ElrondNetwork/elrond-go/process/smartContract/hooks" "github.com/ElrondNetwork/elrond-go/process/transaction" "github.com/ElrondNetwork/elrond-go/sharding" - vmcommon "github.com/ElrondNetwork/elrond-vm-common" "github.com/pkg/errors" ) @@ -81,9 +80,9 @@ type TestProcessorNode struct { TxProcessor process.TransactionProcessor TxCoordinator process.TransactionCoordinator ScrForwarder process.IntermediateTransactionHandler - VmProcessor vmcommon.VMExecutionHandler - VmDataGetter vmcommon.VMExecutionHandler - BlockchainHook vmcommon.BlockchainHook + VmProcessors process.VirtualMachinesContainer + VmDataGetter process.VirtualMachinesContainer + BlockchainHook *hooks.VMAccountsDB ArgsParser process.ArgumentsParser ScProcessor process.SmartContractProcessor PreProcessorsContainer process.PreProcessorsContainer @@ -295,22 +294,17 @@ func (tpn *TestProcessorNode) initInnerProcessors() { tpn.InterimProcContainer, _ = interimProcFactory.Create() tpn.ScrForwarder, _ = tpn.InterimProcContainer.Get(dataBlock.SmartContractResultBlock) - tpn.VmProcessor, tpn.BlockchainHook = CreateIeleVMAndBlockchainHook(tpn.AccntState) - tpn.VmDataGetter, _ = CreateIeleVMAndBlockchainHook(tpn.AccntState) - - vmContainer := &mock.VMContainerMock{ - GetCalled: func(key []byte) (handler vmcommon.VMExecutionHandler, e error) { - return tpn.VmProcessor, nil - }} + tpn.VmProcessors, tpn.BlockchainHook = CreateVMContainerAndBlockchainHook(tpn.AccntState) + tpn.VmDataGetter, _ = CreateVMContainerAndBlockchainHook(tpn.AccntState) tpn.ArgsParser, _ = smartContract.NewAtArgumentParser() tpn.ScProcessor, _ = smartContract.NewSmartContractProcessor( - vmContainer, + tpn.VmProcessors, tpn.ArgsParser, TestHasher, TestMarshalizer, tpn.AccntState, - tpn.BlockchainHook.(*hooks.VMAccountsDB), + tpn.BlockchainHook, TestAddressConverter, tpn.ShardCoordinator, tpn.ScrForwarder, diff --git a/integrationTests/vm/arwen/arwenVM_test.go b/integrationTests/vm/arwen/arwenVM_test.go new file mode 100644 index 00000000000..d69ef39996c --- /dev/null +++ b/integrationTests/vm/arwen/arwenVM_test.go @@ -0,0 +1,199 @@ +package arwen + +import ( + "encoding/hex" + "fmt" + "io/ioutil" + "math/big" + "testing" + "time" + + "github.com/ElrondNetwork/elrond-go/data/transaction" + "github.com/ElrondNetwork/elrond-go/integrationTests/vm" + "github.com/ElrondNetwork/elrond-go/process/factory" + "github.com/stretchr/testify/assert" +) + +func TestVmDeployWithTransferAndGasShouldDeploySCCode(t *testing.T) { + senderAddressBytes := []byte("12345678901234567890123456789012") + senderNonce := uint64(0) + senderBalance := big.NewInt(100000000) + round := uint64(444) + gasPrice := uint64(1) + gasLimit := uint64(100000) + transferOnCalls := big.NewInt(50) + + scCode, err := ioutil.ReadFile("./fib_arwen.wasm") + assert.Nil(t, err) + + scCodeString := hex.EncodeToString(scCode) + + tx := vm.CreateTx( + t, + senderAddressBytes, + vm.CreateEmptyAddress().Bytes(), + senderNonce, + transferOnCalls, + gasPrice, + gasLimit, + scCodeString+"@"+hex.EncodeToString(factory.ArwenVirtualMachine), + ) + + txProc, accnts, _ := vm.CreatePreparedTxProcessorAndAccountsWithVMs(t, senderNonce, senderAddressBytes, senderBalance) + + err = txProc.ProcessTransaction(tx, round) + assert.Nil(t, err) + + _, err = accnts.Commit() + assert.Nil(t, err) + + expectedBalance := big.NewInt(99999700) + fmt.Printf("%s \n", hex.EncodeToString(expectedBalance.Bytes())) + + vm.TestAccount( + t, + accnts, + senderAddressBytes, + senderNonce+1, + expectedBalance) +} + +func Benchmark_VmDeployWithFibbonacciAndExecute(b *testing.B) { + runWASMVMBenchmark(b, "./fib_arwen.wasm", b.N, 32) +} + +func Benchmark_VmDeployWithCPUCalculateAndExecute(b *testing.B) { + runWASMVMBenchmark(b, "./cpucalculate_arwen.wasm", b.N, 8000) +} + +func Benchmark_VmDeployWithStringConcatAndExecute(b *testing.B) { + runWASMVMBenchmark(b, "./stringconcat_arwen.wasm", b.N, 10000) +} + +func runWASMVMBenchmark(tb testing.TB, fileSC string, numRun int, testingValue uint64) { + ownerAddressBytes := []byte("12345678901234567890123456789012") + ownerNonce := uint64(11) + ownerBalance := big.NewInt(100000000) + round := uint64(444) + gasPrice := uint64(1) + gasLimit := uint64(100000) + transferOnCalls := big.NewInt(1) + + scCode, err := ioutil.ReadFile(fileSC) + assert.Nil(tb, err) + + scCodeString := hex.EncodeToString(scCode) + + tx := &transaction.Transaction{ + Nonce: ownerNonce, + Value: transferOnCalls, + RcvAddr: vm.CreateEmptyAddress().Bytes(), + SndAddr: ownerAddressBytes, + GasPrice: gasPrice, + GasLimit: gasLimit, + Data: scCodeString + "@" + hex.EncodeToString(factory.ArwenVirtualMachine), + Signature: nil, + Challenge: nil, + } + + txProc, accnts, blockchainHook := vm.CreatePreparedTxProcessorAndAccountsWithVMs(tb, ownerNonce, ownerAddressBytes, ownerBalance) + scAddress, _ := blockchainHook.NewAddress(ownerAddressBytes, ownerNonce, factory.ArwenVirtualMachine) + + err = txProc.ProcessTransaction(tx, round) + assert.Nil(tb, err) + + _, err = accnts.Commit() + assert.Nil(tb, err) + + alice := []byte("12345678901234567890123456789111") + aliceNonce := uint64(0) + _ = vm.CreateAccount(accnts, alice, aliceNonce, big.NewInt(10000000000)) + + tx = &transaction.Transaction{ + Nonce: aliceNonce, + Value: big.NewInt(0).SetUint64(testingValue), + RcvAddr: scAddress, + SndAddr: alice, + GasPrice: 0, + GasLimit: 5000, + Data: "_main", + Signature: nil, + Challenge: nil, + } + + for i := 0; i < numRun; i++ { + tx.Nonce = aliceNonce + + _ = txProc.ProcessTransaction(tx, round) + + aliceNonce++ + } +} + +func TestVmDeployWithTransferAndExecuteERC20(t *testing.T) { + ownerAddressBytes := []byte("12345678901234567890123456789012") + ownerNonce := uint64(11) + ownerBalance := big.NewInt(100000000) + round := uint64(444) + gasPrice := uint64(1) + gasLimit := uint64(100000) + transferOnCalls := big.NewInt(5) + + scCode, err := ioutil.ReadFile("./wrc20_arwen.wasm") + assert.Nil(t, err) + + scCodeString := hex.EncodeToString(scCode) + + txProc, accnts, blockchainHook := vm.CreatePreparedTxProcessorAndAccountsWithVMs(t, ownerNonce, ownerAddressBytes, ownerBalance) + scAddress, _ := blockchainHook.NewAddress(ownerAddressBytes, ownerNonce, factory.ArwenVirtualMachine) + + tx := vm.CreateDeployTx( + ownerAddressBytes, + ownerNonce, + transferOnCalls, + gasPrice, + gasLimit, + scCodeString+"@"+hex.EncodeToString(factory.ArwenVirtualMachine), + ) + + err = txProc.ProcessTransaction(tx, round) + assert.Nil(t, err) + + alice := []byte("12345678901234567890123456789111") + aliceNonce := uint64(0) + _ = vm.CreateAccount(accnts, alice, aliceNonce, big.NewInt(1000000)) + + bob := []byte("12345678901234567890123456789222") + _ = vm.CreateAccount(accnts, bob, 0, big.NewInt(1000000)) + + initAlice := big.NewInt(100000) + tx = vm.CreateTopUpTx(aliceNonce, initAlice, scAddress, alice) + + err = txProc.ProcessTransaction(tx, round) + assert.Nil(t, err) + + aliceNonce++ + + start := time.Now() + nrTxs := 10000 + + for i := 0; i < nrTxs; i++ { + tx = vm.CreateTransferTx(aliceNonce, transferOnCalls, scAddress, alice, bob) + + err = txProc.ProcessTransaction(tx, round) + assert.Nil(t, err) + + aliceNonce++ + } + + _, err = accnts.Commit() + assert.Nil(t, err) + + elapsedTime := time.Since(start) + fmt.Printf("time elapsed to process %d ERC20 transfers %s \n", nrTxs, elapsedTime.String()) + + finalAlice := big.NewInt(0).Sub(initAlice, big.NewInt(int64(nrTxs)*transferOnCalls.Int64())) + assert.Equal(t, finalAlice.Uint64(), vm.GetIntValueFromSC(accnts, scAddress, "do_balance", alice).Uint64()) + finalBob := big.NewInt(int64(nrTxs) * transferOnCalls.Int64()) + assert.Equal(t, finalBob.Uint64(), vm.GetIntValueFromSC(accnts, scAddress, "do_balance", bob).Uint64()) +} diff --git a/integrationTests/vm/arwen/cpucalculate_arwen.wasm b/integrationTests/vm/arwen/cpucalculate_arwen.wasm new file mode 100755 index 00000000000..9715f6d7353 Binary files /dev/null and b/integrationTests/vm/arwen/cpucalculate_arwen.wasm differ diff --git a/integrationTests/vm/arwen/fib_arwen.wasm b/integrationTests/vm/arwen/fib_arwen.wasm new file mode 100755 index 00000000000..3fe2a5edb26 Binary files /dev/null and b/integrationTests/vm/arwen/fib_arwen.wasm differ diff --git a/integrationTests/vm/arwen/stringconcat_arwen.wasm b/integrationTests/vm/arwen/stringconcat_arwen.wasm new file mode 100755 index 00000000000..46bc14d3199 Binary files /dev/null and b/integrationTests/vm/arwen/stringconcat_arwen.wasm differ diff --git a/integrationTests/vm/arwen/wrc20_arwen.wasm b/integrationTests/vm/arwen/wrc20_arwen.wasm new file mode 100755 index 00000000000..5790ea43f40 Binary files /dev/null and b/integrationTests/vm/arwen/wrc20_arwen.wasm differ diff --git a/integrationTests/vm/iele/vmAgar_test.go b/integrationTests/vm/iele/vmAgar_test.go index 4149602c8cd..4b54d39b81a 100644 --- a/integrationTests/vm/iele/vmAgar_test.go +++ b/integrationTests/vm/iele/vmAgar_test.go @@ -8,10 +8,8 @@ import ( "math/big" "testing" - "github.com/ElrondNetwork/elrond-go/data/state" "github.com/ElrondNetwork/elrond-go/integrationTests/vm" "github.com/ElrondNetwork/elrond-go/process/factory" - "github.com/ElrondNetwork/elrond-go/process/smartContract" "github.com/stretchr/testify/assert" ) @@ -28,7 +26,7 @@ func TestDeployAgarioContract(t *testing.T) { gasPrice := uint64(1) gasLimit := uint64(1000000) - txProc, accnts, blockchainHook := vm.CreatePreparedTxProcessorAndAccountsWithIeleVM(t, senderNonce, senderAddressBytes, senderBalance) + txProc, accnts, blockchainHook := vm.CreatePreparedTxProcessorAndAccountsWithVMs(t, senderNonce, senderAddressBytes, senderBalance) deployContract( t, senderAddressBytes, @@ -63,7 +61,7 @@ func TestAgarioContractTopUpShouldWork(t *testing.T) { gasPrice := uint64(1) gasLimit := uint64(1000000) - txProc, accnts, blockchainHook := vm.CreatePreparedTxProcessorAndAccountsWithIeleVM(t, senderNonce, senderAddressBytes, senderBalance) + txProc, accnts, blockchainHook := vm.CreatePreparedTxProcessorAndAccountsWithVMs(t, senderNonce, senderAddressBytes, senderBalance) deployContract( t, senderAddressBytes, @@ -86,7 +84,7 @@ func TestAgarioContractTopUpShouldWork(t *testing.T) { _, _ = accnts.Commit() //balanceOf should return 0 for userAddress - assert.Equal(t, big.NewInt(0), getIntValueFromSC(accnts, scAddressBytes, "balanceOf", userAddress)) + assert.Equal(t, big.NewInt(0), vm.GetIntValueFromSC(accnts, scAddressBytes, "balanceOf", userAddress)) transfer := big.NewInt(123456) data := "topUp" @@ -108,7 +106,7 @@ func TestAgarioContractTopUpShouldWork(t *testing.T) { _, err = accnts.Commit() assert.Nil(t, err) - assert.Equal(t, transfer, getIntValueFromSC(accnts, scAddressBytes, "balanceOf", userAddress)) + assert.Equal(t, transfer, vm.GetIntValueFromSC(accnts, scAddressBytes, "balanceOf", userAddress)) } func TestAgarioContractTopUpAnfWithdrawShouldWork(t *testing.T) { @@ -122,7 +120,7 @@ func TestAgarioContractTopUpAnfWithdrawShouldWork(t *testing.T) { gasPrice := uint64(1) gasLimit := uint64(100000) - txProc, accnts, blockchainHook := vm.CreatePreparedTxProcessorAndAccountsWithIeleVM(t, senderNonce, senderAddressBytes, senderBalance) + txProc, accnts, blockchainHook := vm.CreatePreparedTxProcessorAndAccountsWithVMs(t, senderNonce, senderAddressBytes, senderBalance) deployContract( t, senderAddressBytes, @@ -145,7 +143,7 @@ func TestAgarioContractTopUpAnfWithdrawShouldWork(t *testing.T) { _, _ = accnts.Commit() //balanceOf should return 0 for userAddress - assert.Equal(t, big.NewInt(0), getIntValueFromSC(accnts, scAddressBytes, "balanceOf", userAddress)) + assert.Equal(t, big.NewInt(0), vm.GetIntValueFromSC(accnts, scAddressBytes, "balanceOf", userAddress)) transfer := big.NewInt(123456) data := "topUp" @@ -168,7 +166,7 @@ func TestAgarioContractTopUpAnfWithdrawShouldWork(t *testing.T) { _, err = accnts.Commit() assert.Nil(t, err) - assert.Equal(t, transfer, getIntValueFromSC(accnts, scAddressBytes, "balanceOf", userAddress)) + assert.Equal(t, transfer, vm.GetIntValueFromSC(accnts, scAddressBytes, "balanceOf", userAddress)) //withdraw withdraw := big.NewInt(49999) @@ -193,7 +191,7 @@ func TestAgarioContractTopUpAnfWithdrawShouldWork(t *testing.T) { newValue := big.NewInt(0).Set(transfer) newValue.Sub(newValue, withdraw) - assert.Equal(t, newValue, getIntValueFromSC(accnts, scAddressBytes, "balanceOf", userAddress)) + assert.Equal(t, newValue, vm.GetIntValueFromSC(accnts, scAddressBytes, "balanceOf", userAddress)) } func TestAgarioContractJoinGameReward(t *testing.T) { @@ -207,7 +205,7 @@ func TestAgarioContractJoinGameReward(t *testing.T) { gasPrice := uint64(0) gasLimit := uint64(100000) - txProc, accnts, blockchainHook := vm.CreatePreparedTxProcessorAndAccountsWithIeleVM(t, senderNonce, senderAddressBytes, senderBalance) + txProc, accnts, blockchainHook := vm.CreatePreparedTxProcessorAndAccountsWithVMs(t, senderNonce, senderAddressBytes, senderBalance) deployContract( t, senderAddressBytes, @@ -247,7 +245,7 @@ func TestAgarioContractJoinGameReward(t *testing.T) { for i := 0; i < noOfUsers; i++ { //balanceOf should return 0 for userAddress - balanceOfUser := getIntValueFromSC(accnts, scAddressBytes, "balanceOf", usersAddresses[i]) + balanceOfUser := vm.GetIntValueFromSC(accnts, scAddressBytes, "balanceOf", usersAddresses[i]) fmt.Printf("balance of user %s: %v\n", hex.EncodeToString(usersAddresses[i]), balanceOfUser) assert.Equal(t, big.NewInt(0), balanceOfUser) } @@ -342,7 +340,7 @@ func BenchmarkAgarioJoinGame(b *testing.B) { gasPrice := uint64(0) gasLimit := uint64(1000000) - txProc, accnts, blockchainHook := vm.CreatePreparedTxProcessorAndAccountsWithIeleVM(b, senderNonce, senderAddressBytes, senderBalance) + txProc, accnts, blockchainHook := vm.CreatePreparedTxProcessorAndAccountsWithVMs(b, senderNonce, senderAddressBytes, senderBalance) deployContract( b, senderAddressBytes, @@ -386,11 +384,3 @@ func BenchmarkAgarioJoinGame(b *testing.B) { _ = txProc.ProcessTransaction(txRun, round) } } - -func getIntValueFromSC(accnts state.AccountsAdapter, scAddressBytes []byte, funcName string, args ...[]byte) *big.Int { - ieleVM, _ := vm.CreateVMAndBlockchainHook(accnts) - scgd, _ := smartContract.NewSCDataGetter(ieleVM) - - returnedVals, _ := scgd.Get(scAddressBytes, funcName, args...) - return big.NewInt(0).SetBytes(returnedVals) -} diff --git a/integrationTests/vm/iele/vmDeploy_test.go b/integrationTests/vm/iele/vmDeploy_test.go index 972aff08be7..3cada8cfa13 100644 --- a/integrationTests/vm/iele/vmDeploy_test.go +++ b/integrationTests/vm/iele/vmDeploy_test.go @@ -23,7 +23,7 @@ func TestVMInvalidSmartContractCodeShouldNotGenerateAccount(t *testing.T) { gasPrice := uint64(1) gasLimit := uint64(1000000) - txProc, accnts, blockchainHook := vm.CreatePreparedTxProcessorAndAccountsWithIeleVM(t, senderNonce, senderAddressBytes, senderBalance) + txProc, accnts, blockchainHook := vm.CreatePreparedTxProcessorAndAccountsWithVMs(t, senderNonce, senderAddressBytes, senderBalance) assert.Equal(t, 0, accnts.JournalLen()) tx := &transaction.Transaction{ @@ -71,7 +71,7 @@ func TestVmDeployWithTransferAndGasShouldDeploySCCode(t *testing.T) { scCode, ) - txProc, accnts, blockchainHook := vm.CreatePreparedTxProcessorAndAccountsWithIeleVM(t, senderNonce, senderAddressBytes, senderBalance) + txProc, accnts, blockchainHook := vm.CreatePreparedTxProcessorAndAccountsWithVMs(t, senderNonce, senderAddressBytes, senderBalance) err := txProc.ProcessTransaction(tx, round) assert.Nil(t, err) @@ -122,7 +122,7 @@ func TestVMDeployWithTransferWithInsufficientGasShouldReturnErr(t *testing.T) { scCode, ) - txProc, accnts, blockchainHook := vm.CreatePreparedTxProcessorAndAccountsWithIeleVM(t, senderNonce, senderAddressBytes, senderBalance) + txProc, accnts, blockchainHook := vm.CreatePreparedTxProcessorAndAccountsWithVMs(t, senderNonce, senderAddressBytes, senderBalance) err := txProc.ProcessTransaction(tx, round) assert.Nil(t, err) diff --git a/integrationTests/vm/iele/vmRunContract_test.go b/integrationTests/vm/iele/vmRunContract_test.go index dd9a780beb5..fc70984126c 100644 --- a/integrationTests/vm/iele/vmRunContract_test.go +++ b/integrationTests/vm/iele/vmRunContract_test.go @@ -26,7 +26,7 @@ func TestRunWithTransferAndGasShouldRunSCCode(t *testing.T) { scCode := fmt.Sprintf("0000003B6302690003616464690004676574416700000001616101550468000100016161015406010A6161015506F6000068000200006161005401F6000101@%s@%X", hex.EncodeToString(factory.IELEVirtualMachine), initialValueForInternalVariable) - txProc, accnts, blockchainHook := vm.CreatePreparedTxProcessorAndAccountsWithIeleVM(t, senderNonce, senderAddressBytes, senderBalance) + txProc, accnts, blockchainHook := vm.CreatePreparedTxProcessorAndAccountsWithVMs(t, senderNonce, senderAddressBytes, senderBalance) deployContract( t, @@ -94,7 +94,7 @@ func TestRunWithTransferWithInsufficientGasShouldReturnErr(t *testing.T) { scCode := fmt.Sprintf("0000003B6302690003616464690004676574416700000001616101550468000100016161015406010A6161015506F6000068000200006161005401F6000101@%s@%X", hex.EncodeToString(factory.IELEVirtualMachine), initialValueForInternalVariable) - txProc, accnts, blockchainHook := vm.CreatePreparedTxProcessorAndAccountsWithIeleVM(t, senderNonce, senderAddressBytes, senderBalance) + txProc, accnts, blockchainHook := vm.CreatePreparedTxProcessorAndAccountsWithVMs(t, senderNonce, senderAddressBytes, senderBalance) //deploy will transfer 0 and will succeed deployContract( t, diff --git a/integrationTests/vm/mockVM/vmGet_test.go b/integrationTests/vm/mockVM/vmGet_test.go index cdf221a3adc..8719f4882dc 100644 --- a/integrationTests/vm/mockVM/vmGet_test.go +++ b/integrationTests/vm/mockVM/vmGet_test.go @@ -7,9 +7,11 @@ import ( "testing" "github.com/ElrondNetwork/elrond-go/data/state" + "github.com/ElrondNetwork/elrond-go/integrationTests/mock" "github.com/ElrondNetwork/elrond-go/integrationTests/vm" "github.com/ElrondNetwork/elrond-go/process/factory" "github.com/ElrondNetwork/elrond-go/process/smartContract" + vmcommon "github.com/ElrondNetwork/elrond-vm-common" "github.com/stretchr/testify/assert" ) @@ -17,7 +19,11 @@ func TestVmGetShouldReturnValue(t *testing.T) { accnts, destinationAddressBytes, expectedValueForVar := deploySmartContract(t) mockVM := vm.CreateOneSCExecutorMockVM(accnts) - scgd, _ := smartContract.NewSCDataGetter(mockVM) + vmContainer := &mock.VMContainerMock{ + GetCalled: func(key []byte) (handler vmcommon.VMExecutionHandler, e error) { + return mockVM, nil + }} + scgd, _ := smartContract.NewSCDataGetter(vmContainer) functionName := "Get" returnedVals, err := scgd.Get(destinationAddressBytes, functionName) diff --git a/integrationTests/vm/testInitializer.go b/integrationTests/vm/testInitializer.go index a6f2118c95b..8e4dab51fe6 100644 --- a/integrationTests/vm/testInitializer.go +++ b/integrationTests/vm/testInitializer.go @@ -13,7 +13,7 @@ import ( "github.com/ElrondNetwork/elrond-go/integrationTests/mock" "github.com/ElrondNetwork/elrond-go/marshal" "github.com/ElrondNetwork/elrond-go/process" - "github.com/ElrondNetwork/elrond-go/process/factory" + "github.com/ElrondNetwork/elrond-go/process/factory/shard" "github.com/ElrondNetwork/elrond-go/process/smartContract" "github.com/ElrondNetwork/elrond-go/process/smartContract/hooks" "github.com/ElrondNetwork/elrond-go/process/transaction" @@ -21,7 +21,6 @@ import ( "github.com/ElrondNetwork/elrond-go/storage/memorydb" "github.com/ElrondNetwork/elrond-go/storage/storageUnit" vmcommon "github.com/ElrondNetwork/elrond-vm-common" - "github.com/ElrondNetwork/elrond-vm/iele/elrond/node/endpoint" "github.com/stretchr/testify/assert" ) @@ -113,25 +112,21 @@ func CreateOneSCExecutorMockVM(accnts state.AccountsAdapter) vmcommon.VMExecutio return vm } -func CreateVMAndBlockchainHook(accnts state.AccountsAdapter) (vmcommon.VMExecutionHandler, *hooks.VMAccountsDB) { +func CreateVMsContainerAndBlockchainHook(accnts state.AccountsAdapter) (process.VirtualMachinesContainer, *hooks.VMAccountsDB) { blockChainHook, _ := hooks.NewVMAccountsDB(accnts, addrConv) - cryptoHook := hooks.NewVMCryptoHook() - vm := endpoint.NewElrondIeleVM(factory.IELEVirtualMachine, endpoint.ElrondTestnet, blockChainHook, cryptoHook) - //Uncomment this to enable trace printing of the vm - //vm.SetTracePretty() - return vm, blockChainHook + vmFactory, _ := shard.NewVMContainerFactory(accnts, addrConv) + vmContainer, _ := vmFactory.Create() + + return vmContainer, blockChainHook } -func CreateTxProcessorWithOneSCExecutorIeleVM( +func CreateTxProcessorWithOneSCExecutorWithVMs( accnts state.AccountsAdapter, ) (process.TransactionProcessor, vmcommon.BlockchainHook) { - vm, blockChainHook := CreateVMAndBlockchainHook(accnts) - vmContainer := &mock.VMContainerMock{ - GetCalled: func(key []byte) (handler vmcommon.VMExecutionHandler, e error) { - return vm, nil - }} + vmFactory, _ := shard.NewVMContainerFactory(accnts, addrConv) + vmContainer, _ := vmFactory.Create() argsParser, _ := smartContract.NewAtArgumentParser() scProcessor, _ := smartContract.NewSmartContractProcessor( @@ -140,14 +135,14 @@ func CreateTxProcessorWithOneSCExecutorIeleVM( testHasher, testMarshalizer, accnts, - blockChainHook, + vmFactory.VMAccountsDB(), addrConv, oneShardCoordinator, &mock.IntermediateTransactionHandlerMock{}, ) txProcessor, _ := transaction.NewTxProcessor(accnts, testHasher, addrConv, testMarshalizer, oneShardCoordinator, scProcessor) - return txProcessor, blockChainHook + return txProcessor, vmFactory.VMAccountsDB() } func TestDeployedContractContents( @@ -193,7 +188,7 @@ func AccountExists(accnts state.AccountsAdapter, addressBytes []byte) bool { return accnt != nil } -func CreatePreparedTxProcessorAndAccountsWithIeleVM( +func CreatePreparedTxProcessorAndAccountsWithVMs( tb testing.TB, senderNonce uint64, senderAddressBytes []byte, @@ -203,7 +198,7 @@ func CreatePreparedTxProcessorAndAccountsWithIeleVM( accnts := CreateInMemoryShardAccountsDB() _ = CreateAccount(accnts, senderAddressBytes, senderNonce, senderBalance) - txProcessor, blockchainHook := CreateTxProcessorWithOneSCExecutorIeleVM(accnts) + txProcessor, blockchainHook := CreateTxProcessorWithOneSCExecutorWithVMs(accnts) assert.NotNil(tb, txProcessor) return txProcessor, accnts, blockchainHook @@ -252,6 +247,26 @@ func CreateTx( return tx } +func CreateDeployTx( + senderAddressBytes []byte, + senderNonce uint64, + value *big.Int, + gasPrice uint64, + gasLimit uint64, + scCodeAndVMType string, +) *dataTransaction.Transaction { + + return &dataTransaction.Transaction{ + Nonce: senderNonce, + Value: value, + SndAddr: senderAddressBytes, + RcvAddr: CreateEmptyAddress().Bytes(), + Data: scCodeAndVMType, + GasPrice: gasPrice, + GasLimit: gasLimit, + } +} + func TestAccount( t *testing.T, accnts state.AccountsAdapter, @@ -289,3 +304,42 @@ func GetAccountsBalance(addrBytes []byte, accnts state.AccountsAdapter) *big.Int return shardAccnt.Balance } + +func GetIntValueFromSC(accnts state.AccountsAdapter, scAddressBytes []byte, funcName string, args ...[]byte) *big.Int { + vmContainer, _ := CreateVMsContainerAndBlockchainHook(accnts) + scgd, _ := smartContract.NewSCDataGetter(vmContainer) + + returnedVals, _ := scgd.Get(scAddressBytes, funcName, args...) + + return big.NewInt(0).SetBytes(returnedVals) +} + +func CreateTopUpTx(nonce uint64, value *big.Int, scAddrress []byte, sndAddress []byte) *dataTransaction.Transaction { + return &dataTransaction.Transaction{ + Nonce: nonce, + Value: value, + RcvAddr: scAddrress, + SndAddr: sndAddress, + GasPrice: 0, + GasLimit: 5000, + Data: "topUp", + } +} + +func CreateTransferTx( + nonce uint64, + value *big.Int, + scAddrress []byte, + sndAddress []byte, + rcvAddress []byte, +) *dataTransaction.Transaction { + return &dataTransaction.Transaction{ + Nonce: nonce, + Value: big.NewInt(0), + RcvAddr: scAddrress, + SndAddr: sndAddress, + GasPrice: 0, + GasLimit: 5000, + Data: "transfer@" + hex.EncodeToString(rcvAddress) + "@" + value.String(), + } +} diff --git a/process/factory/factory.go b/process/factory/factory.go index d65c656aca7..5f064a8a120 100644 --- a/process/factory/factory.go +++ b/process/factory/factory.go @@ -22,3 +22,6 @@ var InternalTestingVM = []byte{0, 0} // IELEVirtualMachine is a byte array identifier for the smart contract address created for IELE VM var IELEVirtualMachine = []byte{1, 0} + +// ArwenVirtualMachine is a byte array identifier for the smart contract address created for Arwen VM +var ArwenVirtualMachine = []byte{5, 0} diff --git a/process/factory/shard/vmContainerFactory.go b/process/factory/shard/vmContainerFactory.go index dcbcbcbd578..5fa63b678b0 100644 --- a/process/factory/shard/vmContainerFactory.go +++ b/process/factory/shard/vmContainerFactory.go @@ -1,6 +1,7 @@ package shard import ( + "github.com/ElrondNetwork/arwen-wasm-vm/arwen" "github.com/ElrondNetwork/elrond-go/data/state" "github.com/ElrondNetwork/elrond-go/process" "github.com/ElrondNetwork/elrond-go/process/factory" @@ -57,6 +58,16 @@ func (vmf *vmContainerFactory) Create() (process.VirtualMachinesContainer, error return nil, err } + vm, err = vmf.createArwenVM() + if err != nil { + return nil, err + } + + err = container.Add(factory.ArwenVirtualMachine, vm) + if err != nil { + return nil, err + } + return container, nil } @@ -65,6 +76,11 @@ func (vmf *vmContainerFactory) createIeleVM() (vmcommon.VMExecutionHandler, erro return ieleVM, nil } +func (vmf *vmContainerFactory) createArwenVM() (vmcommon.VMExecutionHandler, error) { + arwenVM, err := arwen.NewArwenVM(vmf.vmAccountsDB, vmf.cryptoHook, factory.ArwenVirtualMachine) + return arwenVM, err +} + // VMAccountsDB returns the created vmAccountsDB func (vmf *vmContainerFactory) VMAccountsDB() *hooks.VMAccountsDB { return vmf.vmAccountsDB diff --git a/process/smartContract/hooks/vmAccountsDB.go b/process/smartContract/hooks/vmAccountsDB.go index 82c516849ea..3feca12b1e6 100644 --- a/process/smartContract/hooks/vmAccountsDB.go +++ b/process/smartContract/hooks/vmAccountsDB.go @@ -265,3 +265,8 @@ func (vadb *VMAccountsDB) IsInterfaceNil() bool { } return false } + +// VMTypeFromAddressBytes gets VM type from scAddress +func VMTypeFromAddressBytes(scAddress []byte) []byte { + return scAddress[NumInitCharactersForScAddress-VMTypeLen : NumInitCharactersForScAddress] +} diff --git a/process/smartContract/process.go b/process/smartContract/process.go index 2dc1d262b3a..5b834be41fd 100644 --- a/process/smartContract/process.go +++ b/process/smartContract/process.go @@ -185,7 +185,6 @@ func (sc *scProcessor) ExecuteSmartContractTransaction( return err } - // VM is formally verified and the output is correct crossTxs, err := sc.processVMOutput(vmOutput, tx, acntSnd, round) if err != nil { return err @@ -235,7 +234,7 @@ func (sc *scProcessor) getVMTypeFromArguments(arg *big.Int) ([]byte, error) { } func (sc *scProcessor) getVMFromRecvAddress(tx *transaction.Transaction) (vmcommon.VMExecutionHandler, error) { - vmType := tx.RcvAddr[hooks.NumInitCharactersForScAddress-hooks.VMTypeLen : hooks.NumInitCharactersForScAddress] + vmType := hooks.VMTypeFromAddressBytes(tx.RcvAddr) vm, err := sc.vmContainer.Get(vmType) if err != nil { return nil, err diff --git a/process/smartContract/scDataGetter.go b/process/smartContract/scDataGetter.go index d6a87e5660d..e613840997f 100644 --- a/process/smartContract/scDataGetter.go +++ b/process/smartContract/scDataGetter.go @@ -7,6 +7,7 @@ import ( "sync" "github.com/ElrondNetwork/elrond-go/process" + "github.com/ElrondNetwork/elrond-go/process/smartContract/hooks" "github.com/ElrondNetwork/elrond-vm-common" "github.com/pkg/errors" ) @@ -15,24 +16,34 @@ var maxGasValue = big.NewInt(math.MaxInt64) // scDataGetter can execute Get functions over SC to fetch stored values type scDataGetter struct { - vm vmcommon.VMExecutionHandler - mutRunSc sync.Mutex + vmContainer process.VirtualMachinesContainer + mutRunSc sync.Mutex } // NewSCDataGetter returns a new instance of scDataGetter func NewSCDataGetter( - vm vmcommon.VMExecutionHandler, + vmContainer process.VirtualMachinesContainer, ) (*scDataGetter, error) { - if vm == nil { + if vmContainer == nil || vmContainer.IsInterfaceNil() { return nil, process.ErrNoVM } return &scDataGetter{ - vm: vm, + vmContainer: vmContainer, }, nil } +func (scdg *scDataGetter) getVMFromAddress(scAddress []byte) (vmcommon.VMExecutionHandler, error) { + vmType := hooks.VMTypeFromAddressBytes(scAddress) + vm, err := scdg.vmContainer.Get(vmType) + if err != nil { + return nil, err + } + + return vm, nil +} + // Get returns the value as byte slice of the invoked func func (scdg *scDataGetter) Get(scAddress []byte, funcName string, args ...[]byte) ([]byte, error) { if scAddress == nil { @@ -45,8 +56,13 @@ func (scdg *scDataGetter) Get(scAddress []byte, funcName string, args ...[]byte) scdg.mutRunSc.Lock() defer scdg.mutRunSc.Unlock() + vm, err := scdg.getVMFromAddress(scAddress) + if err != nil { + return nil, err + } + vmInput := scdg.createVMCallInput(scAddress, funcName, args...) - vmOutput, err := scdg.vm.RunSmartContractCall(vmInput) + vmOutput, err := vm.RunSmartContractCall(vmInput) if err != nil { return nil, err } diff --git a/process/smartContract/scDataGetter_test.go b/process/smartContract/scDataGetter_test.go index 5d1a5e62cf6..28c538d0d41 100644 --- a/process/smartContract/scDataGetter_test.go +++ b/process/smartContract/scDataGetter_test.go @@ -29,7 +29,7 @@ func TestNewSCDataGetter_ShouldWork(t *testing.T) { t.Parallel() scdg, err := smartContract.NewSCDataGetter( - &mock.VMExecutionHandlerStub{}, + &mock.VMContainerMock{}, ) assert.NotNil(t, scdg) @@ -42,7 +42,7 @@ func TestScDataGetter_GetNilAddressShouldErr(t *testing.T) { t.Parallel() scdg, _ := smartContract.NewSCDataGetter( - &mock.VMExecutionHandlerStub{}, + &mock.VMContainerMock{}, ) output, err := scdg.Get(nil, "function") @@ -55,7 +55,7 @@ func TestScDataGetter_GetEmptyFunctionShouldErr(t *testing.T) { t.Parallel() scdg, _ := smartContract.NewSCDataGetter( - &mock.VMExecutionHandlerStub{}, + &mock.VMContainerMock{}, ) output, err := scdg.Get([]byte("sc address"), "") @@ -72,20 +72,26 @@ func TestScDataGetter_GetShouldReceiveAddrFuncAndArgs(t *testing.T) { addressBytes := []byte("address bytes") wasCalled := false + + mockVM := &mock.VMExecutionHandlerStub{ + RunSmartContractCallCalled: func(input *vmcommon.ContractCallInput) (output *vmcommon.VMOutput, e error) { + wasCalled = true + assert.Equal(t, 2, len(input.Arguments)) + for idx, arg := range args { + assert.Equal(t, arg, input.Arguments[idx].Bytes()) + } + assert.Equal(t, addressBytes, input.CallerAddr) + assert.Equal(t, funcName, input.Function) + + return &vmcommon.VMOutput{ + ReturnCode: vmcommon.Ok, + }, nil + }, + } scdg, _ := smartContract.NewSCDataGetter( - &mock.VMExecutionHandlerStub{ - RunSmartContractCallCalled: func(input *vmcommon.ContractCallInput) (output *vmcommon.VMOutput, e error) { - wasCalled = true - assert.Equal(t, 2, len(input.Arguments)) - for idx, arg := range args { - assert.Equal(t, arg, input.Arguments[idx].Bytes()) - } - assert.Equal(t, addressBytes, input.CallerAddr) - assert.Equal(t, funcName, input.Function) - - return &vmcommon.VMOutput{ - ReturnCode: vmcommon.Ok, - }, nil + &mock.VMContainerMock{ + GetCalled: func(key []byte) (handler vmcommon.VMExecutionHandler, e error) { + return mockVM, nil }, }, ) @@ -98,13 +104,19 @@ func TestScDataGetter_GetReturnsDataShouldRet(t *testing.T) { t.Parallel() data := []*big.Int{big.NewInt(90), big.NewInt(91)} + mockVM := &mock.VMExecutionHandlerStub{ + RunSmartContractCallCalled: func(input *vmcommon.ContractCallInput) (output *vmcommon.VMOutput, e error) { + return &vmcommon.VMOutput{ + ReturnCode: vmcommon.Ok, + ReturnData: data, + }, nil + }, + } + scdg, _ := smartContract.NewSCDataGetter( - &mock.VMExecutionHandlerStub{ - RunSmartContractCallCalled: func(input *vmcommon.ContractCallInput) (output *vmcommon.VMOutput, e error) { - return &vmcommon.VMOutput{ - ReturnCode: vmcommon.Ok, - ReturnData: data, - }, nil + &mock.VMContainerMock{ + GetCalled: func(key []byte) (handler vmcommon.VMExecutionHandler, e error) { + return mockVM, nil }, }, ) @@ -118,12 +130,17 @@ func TestScDataGetter_GetReturnsDataShouldRet(t *testing.T) { func TestScDataGetter_GetReturnsNotOkCodeShouldErr(t *testing.T) { t.Parallel() + mockVM := &mock.VMExecutionHandlerStub{ + RunSmartContractCallCalled: func(input *vmcommon.ContractCallInput) (output *vmcommon.VMOutput, e error) { + return &vmcommon.VMOutput{ + ReturnCode: vmcommon.OutOfGas, + }, nil + }, + } scdg, _ := smartContract.NewSCDataGetter( - &mock.VMExecutionHandlerStub{ - RunSmartContractCallCalled: func(input *vmcommon.ContractCallInput) (output *vmcommon.VMOutput, e error) { - return &vmcommon.VMOutput{ - ReturnCode: vmcommon.OutOfGas, - }, nil + &mock.VMContainerMock{ + GetCalled: func(key []byte) (handler vmcommon.VMExecutionHandler, e error) { + return mockVM, nil }, }, ) @@ -139,21 +156,25 @@ func TestScDataGetter_GetShouldCallRunScSequentially(t *testing.T) { t.Parallel() running := int32(0) + mockVM := &mock.VMExecutionHandlerStub{ + RunSmartContractCallCalled: func(input *vmcommon.ContractCallInput) (output *vmcommon.VMOutput, e error) { + atomic.AddInt32(&running, 1) + time.Sleep(time.Millisecond) - scdg, _ := smartContract.NewSCDataGetter( - &mock.VMExecutionHandlerStub{ - RunSmartContractCallCalled: func(input *vmcommon.ContractCallInput) (output *vmcommon.VMOutput, e error) { - atomic.AddInt32(&running, 1) - time.Sleep(time.Millisecond) - - val := atomic.LoadInt32(&running) - assert.Equal(t, int32(1), val) + val := atomic.LoadInt32(&running) + assert.Equal(t, int32(1), val) - atomic.AddInt32(&running, -1) + atomic.AddInt32(&running, -1) - return &vmcommon.VMOutput{ - ReturnCode: vmcommon.Ok, - }, nil + return &vmcommon.VMOutput{ + ReturnCode: vmcommon.Ok, + }, nil + }, + } + scdg, _ := smartContract.NewSCDataGetter( + &mock.VMContainerMock{ + GetCalled: func(key []byte) (handler vmcommon.VMExecutionHandler, e error) { + return mockVM, nil }, }, ) @@ -163,7 +184,7 @@ func TestScDataGetter_GetShouldCallRunScSequentially(t *testing.T) { wg.Add(noOfGoRoutines) for i := 0; i < noOfGoRoutines; i++ { go func() { - _, _ = scdg.Get([]byte("address"), "function") + _, _ = scdg.Get([]byte("addressaddressaddress"), "function") wg.Done() }() }