aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--accounts/abi/bind/backends/simulated.go2
-rw-r--r--build/testtool/testtool.go2
-rw-r--r--cmd/evm/runner.go4
-rw-r--r--cmd/evm/staterunner.go2
-rw-r--r--cmd/govtool/main.go8
-rw-r--r--cmd/utils/flags.go2
-rw-r--r--consensus/clique/snapshot_test.go2
-rw-r--r--consensus/dexcon/dexcon.go2
-rw-r--r--consensus/dexcon/dexcon_test.go2
-rw-r--r--core/asm/asm.go2
-rw-r--r--core/asm/compiler.go2
-rw-r--r--core/bench_test.go2
-rw-r--r--core/block_validator_test.go2
-rw-r--r--core/blockchain.go2
-rw-r--r--core/blockchain_test.go2
-rw-r--r--core/chain_makers_test.go2
-rw-r--r--core/dao_test.go2
-rw-r--r--core/evm.go2
-rw-r--r--core/genesis.go2
-rw-r--r--core/genesis_test.go2
-rw-r--r--core/governance.go2
-rw-r--r--core/headerchain.go6
-rw-r--r--core/state_processor.go2
-rw-r--r--core/state_transition.go17
-rw-r--r--core/types.go2
-rw-r--r--core/vm/common.go12
-rw-r--r--core/vm/evm/analysis.go (renamed from core/vm/analysis.go)2
-rw-r--r--core/vm/evm/analysis_test.go (renamed from core/vm/analysis_test.go)2
-rw-r--r--core/vm/evm/contract.go (renamed from core/vm/contract.go)2
-rw-r--r--core/vm/evm/contracts.go (renamed from core/vm/contracts.go)37
-rw-r--r--core/vm/evm/contracts_test.go (renamed from core/vm/contracts_test.go)2
-rw-r--r--core/vm/evm/doc.go (renamed from core/vm/doc.go)2
-rw-r--r--core/vm/evm/evm.go (renamed from core/vm/evm.go)27
-rw-r--r--core/vm/evm/evm_test.go (renamed from core/vm/evm_test.go)2
-rw-r--r--core/vm/evm/gas.go (renamed from core/vm/gas.go)2
-rw-r--r--core/vm/evm/gas_table.go (renamed from core/vm/gas_table.go)95
-rw-r--r--core/vm/evm/gas_table_test.go (renamed from core/vm/gas_table_test.go)12
-rw-r--r--core/vm/evm/gen_structlog.go (renamed from core/vm/gen_structlog.go)2
-rw-r--r--core/vm/evm/governance.go2198
-rw-r--r--core/vm/evm/governance_abi.go1133
-rw-r--r--core/vm/evm/governance_test.go1060
-rw-r--r--core/vm/evm/instructions.go (renamed from core/vm/instructions.go)517
-rw-r--r--core/vm/evm/instructions_test.go (renamed from core/vm/instructions_test.go)87
-rw-r--r--core/vm/evm/interface.go (renamed from core/vm/interface.go)2
-rw-r--r--core/vm/evm/interpreter.go (renamed from core/vm/interpreter.go)31
-rw-r--r--core/vm/evm/jump_table.go (renamed from core/vm/jump_table.go)292
-rw-r--r--core/vm/evm/logger.go (renamed from core/vm/logger.go)23
-rw-r--r--core/vm/evm/logger_json.go (renamed from core/vm/logger_json.go)9
-rw-r--r--core/vm/evm/logger_test.go (renamed from core/vm/logger_test.go)11
-rw-r--r--core/vm/evm/memory_table.go98
-rw-r--r--core/vm/evm/opcodes.go (renamed from core/vm/opcodes.go)2
-rw-r--r--core/vm/evm/runtime/doc.go (renamed from core/vm/runtime/doc.go)0
-rw-r--r--core/vm/evm/runtime/env.go (renamed from core/vm/runtime/env.go)2
-rw-r--r--core/vm/evm/runtime/fuzz.go (renamed from core/vm/runtime/fuzz.go)0
-rw-r--r--core/vm/evm/runtime/runtime.go (renamed from core/vm/runtime/runtime.go)2
-rw-r--r--core/vm/evm/runtime/runtime_example_test.go (renamed from core/vm/runtime/runtime_example_test.go)2
-rw-r--r--core/vm/evm/runtime/runtime_test.go (renamed from core/vm/runtime/runtime_test.go)2
-rw-r--r--core/vm/evm/stack.go24
-rw-r--r--core/vm/int_pool_verifier.go4
-rw-r--r--core/vm/int_pool_verifier_empty.go4
-rw-r--r--core/vm/intpool.go74
-rw-r--r--core/vm/intpool_test.go26
-rw-r--r--core/vm/memory.go48
-rw-r--r--core/vm/memory_table.go97
-rw-r--r--core/vm/oracle_contracts.go2
-rw-r--r--core/vm/stack.go69
-rw-r--r--core/vm/stack_table.go20
-rw-r--r--dex/api_backend.go2
-rw-r--r--dex/api_tracer.go14
-rw-r--r--dex/backend.go2
-rw-r--r--dex/downloader/downloader.go2
-rw-r--r--dex/downloader/downloader_test.go2
-rw-r--r--dex/downloader/testchain_test.go2
-rw-r--r--dex/governance.go2
-rw-r--r--dex/helper_test.go2
-rw-r--r--eth/api_backend.go2
-rw-r--r--eth/api_tracer.go2
-rw-r--r--eth/backend.go2
-rw-r--r--eth/handler_test.go2
-rw-r--r--eth/helper_test.go2
-rw-r--r--eth/tracers/tracer.go27
-rw-r--r--eth/tracers/tracer_test.go2
-rw-r--r--eth/tracers/tracers_test.go2
-rw-r--r--indexer/blockchain.go2
-rw-r--r--internal/ethapi/api.go2
-rw-r--r--internal/ethapi/backend.go2
-rw-r--r--les/api_backend.go2
-rw-r--r--les/helper_test.go2
-rw-r--r--les/odr_test.go2
-rw-r--r--light/odr_test.go2
-rw-r--r--light/trie_test.go2
-rw-r--r--light/txpool_test.go2
-rw-r--r--miner/worker_test.go2
-rw-r--r--tests/block_test_util.go2
-rw-r--r--tests/state_test.go2
-rw-r--r--tests/state_test_util.go2
-rw-r--r--tests/vm_test.go2
-rw-r--r--tests/vm_test_util.go2
98 files changed, 5313 insertions, 901 deletions
diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go
index 00e5cf482..da307663c 100644
--- a/accounts/abi/bind/backends/simulated.go
+++ b/accounts/abi/bind/backends/simulated.go
@@ -34,7 +34,7 @@ import (
"github.com/dexon-foundation/dexon/core/rawdb"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/eth/filters"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/event"
diff --git a/build/testtool/testtool.go b/build/testtool/testtool.go
index f9d238695..db74bd419 100644
--- a/build/testtool/testtool.go
+++ b/build/testtool/testtool.go
@@ -17,7 +17,7 @@ import (
"github.com/dexon-foundation/dexon/accounts/abi"
"github.com/dexon-foundation/dexon/cmd/zoo/monkey"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/ethclient"
"github.com/dexon-foundation/dexon/internal/build"
diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go
index 114b9fd60..48782b496 100644
--- a/cmd/evm/runner.go
+++ b/cmd/evm/runner.go
@@ -32,8 +32,8 @@ import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/core"
"github.com/dexon-foundation/dexon/core/state"
- "github.com/dexon-foundation/dexon/core/vm"
- "github.com/dexon-foundation/dexon/core/vm/runtime"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
+ "github.com/dexon-foundation/dexon/core/vm/evm/runtime"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/log"
"github.com/dexon-foundation/dexon/params"
diff --git a/cmd/evm/staterunner.go b/cmd/evm/staterunner.go
index b76dc3ca4..ee96a539c 100644
--- a/cmd/evm/staterunner.go
+++ b/cmd/evm/staterunner.go
@@ -24,7 +24,7 @@ import (
"os"
"github.com/dexon-foundation/dexon/core/state"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/log"
"github.com/dexon-foundation/dexon/tests"
diff --git a/cmd/govtool/main.go b/cmd/govtool/main.go
index 1425b9faf..3bd5897a2 100644
--- a/cmd/govtool/main.go
+++ b/cmd/govtool/main.go
@@ -9,7 +9,7 @@ import (
coreTypes "github.com/dexon-foundation/dexon-consensus/core/types"
dkgTypes "github.com/dexon-foundation/dexon-consensus/core/types/dkg"
"github.com/dexon-foundation/dexon/cmd/utils"
- "github.com/dexon-foundation/dexon/core/vm"
+ "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/rlp"
"gopkg.in/urfave/cli.v1"
)
@@ -42,7 +42,7 @@ func decodeInput(ctx *cli.Context) error {
}
// Parse input.
- method, exists := vm.GovernanceABI.Sig2Method[string(input[:4])]
+ method, exists := evm.GovernanceABI.Sig2Method[string(input[:4])]
if !exists {
utils.Fatalf("invalid method")
}
@@ -110,7 +110,7 @@ func decodeInput(ctx *cli.Context) error {
utils.Fatalf("%s", err)
}
switch args.Type.Uint64() {
- case vm.FineTypeForkVote:
+ case evm.FineTypeForkVote:
vote1 := new(coreTypes.Vote)
if err := rlp.DecodeBytes(args.Arg1, vote1); err != nil {
utils.Fatalf("%s", err)
@@ -121,7 +121,7 @@ func decodeInput(ctx *cli.Context) error {
}
fmt.Printf("Vote1: %+v\n", vote1)
fmt.Printf("Vote2: %+v\n", vote2)
- case vm.FineTypeForkBlock:
+ case evm.FineTypeForkBlock:
block1 := new(coreTypes.Block)
if err := rlp.DecodeBytes(args.Arg1, block1); err != nil {
utils.Fatalf("%s", err)
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 6ac26d1fe..03540a33c 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -37,7 +37,7 @@ import (
"github.com/dexon-foundation/dexon/consensus/ethash"
"github.com/dexon-foundation/dexon/core"
"github.com/dexon-foundation/dexon/core/state"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/dashboard"
"github.com/dexon-foundation/dexon/dex"
diff --git a/consensus/clique/snapshot_test.go b/consensus/clique/snapshot_test.go
index d60005c7c..4ea86a77f 100644
--- a/consensus/clique/snapshot_test.go
+++ b/consensus/clique/snapshot_test.go
@@ -25,7 +25,7 @@ import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/core"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/params"
diff --git a/consensus/dexcon/dexcon.go b/consensus/dexcon/dexcon.go
index ae7ff0368..e00bea1fc 100644
--- a/consensus/dexcon/dexcon.go
+++ b/consensus/dexcon/dexcon.go
@@ -26,7 +26,7 @@ import (
"github.com/dexon-foundation/dexon/consensus"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/log"
"github.com/dexon-foundation/dexon/rpc"
)
diff --git a/consensus/dexcon/dexcon_test.go b/consensus/dexcon/dexcon_test.go
index af20fbb1e..a08c25eb3 100644
--- a/consensus/dexcon/dexcon_test.go
+++ b/consensus/dexcon/dexcon_test.go
@@ -25,7 +25,7 @@ import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/core/state"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/params"
diff --git a/core/asm/asm.go b/core/asm/asm.go
index 8dbb45ed3..164f3c29e 100644
--- a/core/asm/asm.go
+++ b/core/asm/asm.go
@@ -21,7 +21,7 @@ import (
"encoding/hex"
"fmt"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
)
// Iterator for disassembled EVM instructions
diff --git a/core/asm/compiler.go b/core/asm/compiler.go
index b1c7c76f0..9a2f4a9aa 100644
--- a/core/asm/compiler.go
+++ b/core/asm/compiler.go
@@ -23,7 +23,7 @@ import (
"strings"
"github.com/dexon-foundation/dexon/common/math"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
)
// Compiler contains information about the parsed source
diff --git a/core/bench_test.go b/core/bench_test.go
index c9a9bf735..98d46176a 100644
--- a/core/bench_test.go
+++ b/core/bench_test.go
@@ -28,7 +28,7 @@ import (
"github.com/dexon-foundation/dexon/consensus/ethash"
"github.com/dexon-foundation/dexon/core/rawdb"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/params"
diff --git a/core/block_validator_test.go b/core/block_validator_test.go
index f22653aca..5ae85c796 100644
--- a/core/block_validator_test.go
+++ b/core/block_validator_test.go
@@ -23,7 +23,7 @@ import (
"github.com/dexon-foundation/dexon/consensus/ethash"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/params"
)
diff --git a/core/blockchain.go b/core/blockchain.go
index c243c8fc5..8037834c1 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -41,7 +41,7 @@ import (
"github.com/dexon-foundation/dexon/core/rawdb"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/event"
diff --git a/core/blockchain_test.go b/core/blockchain_test.go
index f8956da46..c760252d8 100644
--- a/core/blockchain_test.go
+++ b/core/blockchain_test.go
@@ -34,7 +34,7 @@ import (
"github.com/dexon-foundation/dexon/core/rawdb"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/params"
diff --git a/core/chain_makers_test.go b/core/chain_makers_test.go
index 97896e87d..78c242df1 100644
--- a/core/chain_makers_test.go
+++ b/core/chain_makers_test.go
@@ -22,7 +22,7 @@ import (
"github.com/dexon-foundation/dexon/consensus/ethash"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/params"
diff --git a/core/dao_test.go b/core/dao_test.go
index 785aab5f2..7e437c1d9 100644
--- a/core/dao_test.go
+++ b/core/dao_test.go
@@ -21,7 +21,7 @@ import (
"testing"
"github.com/dexon-foundation/dexon/consensus/ethash"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/params"
)
diff --git a/core/evm.go b/core/evm.go
index a2b61c535..83a789131 100644
--- a/core/evm.go
+++ b/core/evm.go
@@ -23,7 +23,7 @@ import (
"github.com/dexon-foundation/dexon/consensus"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
)
// ChainContext supports retrieving headers and consensus parameters from the
diff --git a/core/genesis.go b/core/genesis.go
index 48e1466e1..8f308d7dd 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -32,7 +32,7 @@ import (
"github.com/dexon-foundation/dexon/core/rawdb"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/log"
"github.com/dexon-foundation/dexon/params"
diff --git a/core/genesis_test.go b/core/genesis_test.go
index 16958eac3..718f65e9d 100644
--- a/core/genesis_test.go
+++ b/core/genesis_test.go
@@ -25,7 +25,7 @@ import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/consensus/ethash"
"github.com/dexon-foundation/dexon/core/rawdb"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/params"
)
diff --git a/core/governance.go b/core/governance.go
index 277b3bb89..5344479ff 100644
--- a/core/governance.go
+++ b/core/governance.go
@@ -18,7 +18,7 @@ import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/core/state"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/log"
)
diff --git a/core/headerchain.go b/core/headerchain.go
index ef77aa28a..07a6f9d55 100644
--- a/core/headerchain.go
+++ b/core/headerchain.go
@@ -37,7 +37,7 @@ import (
"github.com/dexon-foundation/dexon/consensus/dexcon"
"github.com/dexon-foundation/dexon/core/rawdb"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/log"
@@ -421,9 +421,9 @@ func newHeaderVerifierCache(
}
}
-func (c *headerVerifierCache) state(round uint64) *vm.GovernanceState {
+func (c *headerVerifierCache) state(round uint64) *evm.GovernanceState {
if state, exist := c.stateCache.Get(round); exist {
- return state.(*vm.GovernanceState)
+ return state.(*evm.GovernanceState)
}
state := c.gov.GetStateForConfigAtRound(round)
c.stateCache.Add(round, state)
diff --git a/core/state_processor.go b/core/state_processor.go
index eaeb36f78..ff2d5fbe4 100644
--- a/core/state_processor.go
+++ b/core/state_processor.go
@@ -22,7 +22,7 @@ import (
"github.com/dexon-foundation/dexon/consensus/misc"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/params"
)
diff --git a/core/state_transition.go b/core/state_transition.go
index f5ac9bde6..fddb187af 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -26,6 +26,7 @@ import (
dexCore "github.com/dexon-foundation/dexon-consensus/core"
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/core/vm"
+ "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/log"
"github.com/dexon-foundation/dexon/params"
)
@@ -69,8 +70,8 @@ type StateTransition struct {
initialGas uint64
value *big.Int
data []byte
- state vm.StateDB
- evm *vm.EVM
+ state evm.StateDB
+ evm *evm.EVM
}
// Message represents a message sent to a contract.
@@ -122,7 +123,7 @@ func IntrinsicGas(data []byte, contractCreation, homestead bool) (uint64, error)
}
// NewStateTransition initialises and returns a new state transition object.
-func NewStateTransition(evm *vm.EVM, msg Message, gp *GasPool) *StateTransition {
+func NewStateTransition(evm *evm.EVM, msg Message, gp *GasPool) *StateTransition {
return &StateTransition{
gp: gp,
evm: evm,
@@ -141,7 +142,7 @@ func NewStateTransition(evm *vm.EVM, msg Message, gp *GasPool) *StateTransition
// the gas used (which includes gas refunds) and an error if it failed. An error always
// indicates a core error meaning that the message would always fail for that particular
// state and would never be accepted within a block.
-func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool) ([]byte, uint64, bool, error) {
+func ApplyMessage(evm *evm.EVM, msg Message, gp *GasPool) ([]byte, uint64, bool, error) {
return NewStateTransition(evm, msg, gp).TransitionDb()
}
@@ -205,7 +206,7 @@ func (st *StateTransition) inExtendedRound() bool {
}
}
- gs := vm.GovernanceState{st.state}
+ gs := evm.GovernanceState{st.state}
round := st.evm.Round.Uint64()
if round < dexCore.ConfigRoundShift {
@@ -219,7 +220,7 @@ func (st *StateTransition) inExtendedRound() bool {
if err != nil {
panic(err)
}
- rgs := vm.GovernanceState{state}
+ rgs := evm.GovernanceState{state}
roundEnd := gs.RoundHeight(st.evm.Round).Uint64() + rgs.RoundLength().Uint64()
@@ -245,7 +246,7 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
return
}
msg := st.msg
- sender := vm.AccountRef(msg.From())
+ sender := evm.AccountRef(msg.From())
homestead := st.evm.ChainConfig().IsHomestead(st.evm.BlockNumber)
contractCreation := msg.To() == nil
@@ -290,7 +291,7 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
receiver := st.evm.Coinbase
if !*legacyEvm && st.inExtendedRound() {
- gs := vm.GovernanceState{st.state}
+ gs := evm.GovernanceState{st.state}
receiver = gs.Owner()
}
diff --git a/core/types.go b/core/types.go
index 04a787b1e..b020a5df7 100644
--- a/core/types.go
+++ b/core/types.go
@@ -20,7 +20,7 @@ import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
)
// Validator is an interface which defines the standard for block validation. It
diff --git a/core/vm/common.go b/core/vm/common.go
index 7702b2a86..6b8c4667b 100644
--- a/core/vm/common.go
+++ b/core/vm/common.go
@@ -24,7 +24,7 @@ import (
)
// calculates the memory size required for a step
-func calcMemSize(off, l *big.Int) *big.Int {
+func CalcMemSize(off, l *big.Int) *big.Int {
if l.Sign() == 0 {
return common.Big0
}
@@ -34,7 +34,7 @@ func calcMemSize(off, l *big.Int) *big.Int {
// getData returns a slice from the data based on the start and size and pads
// up to size with zero's. This function is overflow safe.
-func getData(data []byte, start uint64, size uint64) []byte {
+func GetData(data []byte, start uint64, size uint64) []byte {
length := uint64(len(data))
if start > length {
start = length
@@ -48,7 +48,7 @@ func getData(data []byte, start uint64, size uint64) []byte {
// getDataBig returns a slice from the data based on the start and size and pads
// up to size with zero's. This function is overflow safe.
-func getDataBig(data []byte, start *big.Int, size *big.Int) []byte {
+func GetDataBig(data []byte, start *big.Int, size *big.Int) []byte {
dlen := big.NewInt(int64(len(data)))
s := math.BigMin(start, dlen)
@@ -58,12 +58,12 @@ func getDataBig(data []byte, start *big.Int, size *big.Int) []byte {
// bigUint64 returns the integer casted to a uint64 and returns whether it
// overflowed in the process.
-func bigUint64(v *big.Int) (uint64, bool) {
+func BigUint64(v *big.Int) (uint64, bool) {
return v.Uint64(), v.BitLen() > 64
}
// toWordSize returns the ceiled word size required for memory expansion.
-func toWordSize(size uint64) uint64 {
+func ToWordSize(size uint64) uint64 {
if size > math.MaxUint64-31 {
return math.MaxUint64/32 + 1
}
@@ -71,7 +71,7 @@ func toWordSize(size uint64) uint64 {
return (size + 31) / 32
}
-func allZero(b []byte) bool {
+func AllZero(b []byte) bool {
for _, byte := range b {
if byte != 0 {
return false
diff --git a/core/vm/analysis.go b/core/vm/evm/analysis.go
index 0ccf47b97..5e430f965 100644
--- a/core/vm/analysis.go
+++ b/core/vm/evm/analysis.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package vm
+package evm
// bitvec is a bit vector which maps bytes in a program.
// An unset bit means the byte is an opcode, a set bit means
diff --git a/core/vm/analysis_test.go b/core/vm/evm/analysis_test.go
index c4fe93474..6805f6076 100644
--- a/core/vm/analysis_test.go
+++ b/core/vm/evm/analysis_test.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package vm
+package evm
import (
"testing"
diff --git a/core/vm/contract.go b/core/vm/evm/contract.go
index 751da072e..a7ce2ddfd 100644
--- a/core/vm/contract.go
+++ b/core/vm/evm/contract.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package vm
+package evm
import (
"math/big"
diff --git a/core/vm/contracts.go b/core/vm/evm/contracts.go
index ac8fd22df..52bb0a83b 100644
--- a/core/vm/contracts.go
+++ b/core/vm/evm/contracts.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package vm
+package evm
import (
"crypto/sha256"
@@ -23,6 +23,7 @@ import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/common/math"
+ "github.com/dexon-foundation/dexon/core/vm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/crypto/bn256"
"github.com/dexon-foundation/dexon/params"
@@ -65,7 +66,7 @@ func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contr
if contract.UseGas(gas) {
return p.Run(input)
}
- return nil, ErrOutOfGas
+ return nil, vm.ErrOutOfGas
}
// ECRECOVER implemented as a native contract.
@@ -87,7 +88,7 @@ func (c *ecrecover) Run(input []byte) ([]byte, error) {
v := input[63] - 27
// tighter sig s values input homestead only apply to tx sigs
- if !allZero(input[32:63]) || !crypto.ValidateSignatureValues(v, r, s, false) {
+ if !vm.AllZero(input[32:63]) || !crypto.ValidateSignatureValues(v, r, s, false) {
return nil, nil
}
// v needs to be at the end for libsecp256k1
@@ -166,9 +167,9 @@ var (
// RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bigModExp) RequiredGas(input []byte) uint64 {
var (
- baseLen = new(big.Int).SetBytes(getData(input, 0, 32))
- expLen = new(big.Int).SetBytes(getData(input, 32, 32))
- modLen = new(big.Int).SetBytes(getData(input, 64, 32))
+ baseLen = new(big.Int).SetBytes(vm.GetData(input, 0, 32))
+ expLen = new(big.Int).SetBytes(vm.GetData(input, 32, 32))
+ modLen = new(big.Int).SetBytes(vm.GetData(input, 64, 32))
)
if len(input) > 96 {
input = input[96:]
@@ -181,9 +182,9 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 {
expHead = new(big.Int)
} else {
if expLen.Cmp(big32) > 0 {
- expHead = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), 32))
+ expHead = new(big.Int).SetBytes(vm.GetData(input, baseLen.Uint64(), 32))
} else {
- expHead = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), expLen.Uint64()))
+ expHead = new(big.Int).SetBytes(vm.GetData(input, baseLen.Uint64(), expLen.Uint64()))
}
}
// Calculate the adjusted exponent length
@@ -225,9 +226,9 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 {
func (c *bigModExp) Run(input []byte) ([]byte, error) {
var (
- baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64()
- expLen = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64()
- modLen = new(big.Int).SetBytes(getData(input, 64, 32)).Uint64()
+ baseLen = new(big.Int).SetBytes(vm.GetData(input, 0, 32)).Uint64()
+ expLen = new(big.Int).SetBytes(vm.GetData(input, 32, 32)).Uint64()
+ modLen = new(big.Int).SetBytes(vm.GetData(input, 64, 32)).Uint64()
)
if len(input) > 96 {
input = input[96:]
@@ -240,9 +241,9 @@ func (c *bigModExp) Run(input []byte) ([]byte, error) {
}
// Retrieve the operands and execute the exponentiation
var (
- base = new(big.Int).SetBytes(getData(input, 0, baseLen))
- exp = new(big.Int).SetBytes(getData(input, baseLen, expLen))
- mod = new(big.Int).SetBytes(getData(input, baseLen+expLen, modLen))
+ base = new(big.Int).SetBytes(vm.GetData(input, 0, baseLen))
+ exp = new(big.Int).SetBytes(vm.GetData(input, baseLen, expLen))
+ mod = new(big.Int).SetBytes(vm.GetData(input, baseLen+expLen, modLen))
)
if mod.BitLen() == 0 {
// Modulo 0 is undefined, return zero
@@ -280,11 +281,11 @@ func (c *bn256Add) RequiredGas(input []byte) uint64 {
}
func (c *bn256Add) Run(input []byte) ([]byte, error) {
- x, err := newCurvePoint(getData(input, 0, 64))
+ x, err := newCurvePoint(vm.GetData(input, 0, 64))
if err != nil {
return nil, err
}
- y, err := newCurvePoint(getData(input, 64, 64))
+ y, err := newCurvePoint(vm.GetData(input, 64, 64))
if err != nil {
return nil, err
}
@@ -302,12 +303,12 @@ func (c *bn256ScalarMul) RequiredGas(input []byte) uint64 {
}
func (c *bn256ScalarMul) Run(input []byte) ([]byte, error) {
- p, err := newCurvePoint(getData(input, 0, 64))
+ p, err := newCurvePoint(vm.GetData(input, 0, 64))
if err != nil {
return nil, err
}
res := new(bn256.G1)
- res.ScalarMult(p, new(big.Int).SetBytes(getData(input, 64, 32)))
+ res.ScalarMult(p, new(big.Int).SetBytes(vm.GetData(input, 64, 32)))
return res.Marshal(), nil
}
diff --git a/core/vm/contracts_test.go b/core/vm/evm/contracts_test.go
index f0090fcce..4b43f777b 100644
--- a/core/vm/contracts_test.go
+++ b/core/vm/evm/contracts_test.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package vm
+package evm
import (
"fmt"
diff --git a/core/vm/doc.go b/core/vm/evm/doc.go
index 5864d0cfa..27986e0c4 100644
--- a/core/vm/doc.go
+++ b/core/vm/evm/doc.go
@@ -21,4 +21,4 @@ The vm package implements one EVM, a byte code VM. The BC (Byte Code) VM loops
over a set of bytes and executes them according to the set of rules defined
in the Ethereum yellow paper.
*/
-package vm
+package evm
diff --git a/core/vm/evm.go b/core/vm/evm/evm.go
index baf3a0ac9..11d25792e 100644
--- a/core/vm/evm.go
+++ b/core/vm/evm/evm.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package vm
+package evm
import (
"math/big"
@@ -23,6 +23,7 @@ import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/core/state"
+ "github.com/dexon-foundation/dexon/core/vm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/params"
)
@@ -72,7 +73,7 @@ func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, err
return interpreter.Run(contract, input, readOnly)
}
}
- return nil, ErrNoCompatibleInterpreter
+ return nil, vm.ErrNoCompatibleInterpreter
}
// Context provides the EVM with auxiliary information. Once provided
@@ -201,11 +202,11 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
// Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) {
- return nil, gas, ErrDepth
+ return nil, gas, vm.ErrDepth
}
// Fail if we're trying to transfer more than the available balance
if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
- return nil, gas, ErrInsufficientBalance
+ return nil, gas, vm.ErrInsufficientBalance
}
var (
@@ -273,11 +274,11 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
// Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) {
- return nil, gas, ErrDepth
+ return nil, gas, vm.ErrDepth
}
// Fail if we're trying to transfer more than the available balance
if !evm.CanTransfer(evm.StateDB, caller.Address(), value) {
- return nil, gas, ErrInsufficientBalance
+ return nil, gas, vm.ErrInsufficientBalance
}
var (
@@ -311,7 +312,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
}
// Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) {
- return nil, gas, ErrDepth
+ return nil, gas, vm.ErrDepth
}
var (
@@ -343,7 +344,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
}
// Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) {
- return nil, gas, ErrDepth
+ return nil, gas, vm.ErrDepth
}
var (
@@ -392,10 +393,10 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
// Depth check execution. Fail if we're trying to execute above the
// limit.
if evm.depth > int(params.CallCreateDepth) {
- return nil, common.Address{}, gas, ErrDepth
+ return nil, common.Address{}, gas, vm.ErrDepth
}
if !evm.CanTransfer(evm.StateDB, caller.Address(), value) {
- return nil, common.Address{}, gas, ErrInsufficientBalance
+ return nil, common.Address{}, gas, vm.ErrInsufficientBalance
}
nonce := evm.StateDB.GetNonce(caller.Address())
evm.StateDB.SetNonce(caller.Address(), nonce+1)
@@ -403,7 +404,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
// Ensure there's no existing contract already at the designated address
contractHash := evm.StateDB.GetCodeHash(address)
if evm.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != emptyCodeHash) {
- return nil, common.Address{}, 0, ErrContractAddressCollision
+ return nil, common.Address{}, 0, vm.ErrContractAddressCollision
}
// Create a new account on the state
snapshot := evm.StateDB.Snapshot()
@@ -441,14 +442,14 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
if contract.UseGas(createDataGas) {
evm.StateDB.SetCode(address, ret)
} else {
- err = ErrCodeStoreOutOfGas
+ err = vm.ErrCodeStoreOutOfGas
}
}
// When an error was returned by the EVM or when setting the creation code
// above we revert to the snapshot and consume any gas remaining. Additionally
// when we're in homestead this also counts for code storage gas errors.
- if maxCodeSizeExceeded || (err != nil && (evm.ChainConfig().IsHomestead(evm.BlockNumber) || err != ErrCodeStoreOutOfGas)) {
+ if maxCodeSizeExceeded || (err != nil && (evm.ChainConfig().IsHomestead(evm.BlockNumber) || err != vm.ErrCodeStoreOutOfGas)) {
evm.StateDB.RevertToSnapshot(snapshot)
if err != errExecutionReverted {
contract.UseGas(contract.Gas)
diff --git a/core/vm/evm_test.go b/core/vm/evm/evm_test.go
index 4b2714351..2e382c15f 100644
--- a/core/vm/evm_test.go
+++ b/core/vm/evm/evm_test.go
@@ -15,7 +15,7 @@
// along with the dexon-consensus library. If not, see
// <http://www.gnu.org/licenses/>.
-package vm
+package evm
import (
"fmt"
diff --git a/core/vm/gas.go b/core/vm/evm/gas.go
index 52c3b02f1..edd772423 100644
--- a/core/vm/gas.go
+++ b/core/vm/evm/gas.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package vm
+package evm
import (
"math/big"
diff --git a/core/vm/gas_table.go b/core/vm/evm/gas_table.go
index 0126e26d4..0087004cf 100644
--- a/core/vm/gas_table.go
+++ b/core/vm/evm/gas_table.go
@@ -14,17 +14,18 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package vm
+package evm
import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/common/math"
+ "github.com/dexon-foundation/dexon/core/vm"
"github.com/dexon-foundation/dexon/params"
)
// memoryGasCosts calculates the quadratic gas for memory expansion. It does so
// only for the memory region that is expanded, not the total memory.
-func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) {
+func memoryGasCost(mem *vm.Memory, newMemSize uint64) (uint64, error) {
if newMemSize == 0 {
return 0, nil
@@ -40,7 +41,7 @@ func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) {
return 0, errGasUintOverflow
}
- newMemSizeWords := toWordSize(newMemSize)
+ newMemSizeWords := vm.ToWordSize(newMemSize)
newMemSize = newMemSizeWords * 32
if newMemSize > uint64(mem.Len()) {
@@ -49,8 +50,8 @@ func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) {
quadCoef := square / params.QuadCoeffDiv
newTotalFee := linCoef + quadCoef
- fee := newTotalFee - mem.lastGasCost
- mem.lastGasCost = newTotalFee
+ fee := newTotalFee - mem.LastGasCost
+ mem.LastGasCost = newTotalFee
return fee, nil
}
@@ -58,12 +59,12 @@ func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) {
}
func constGasFunc(gas uint64) gasFunc {
- return func(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+ return func(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
return gas, nil
}
}
-func gasCallDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasCallDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
return 0, err
@@ -74,12 +75,12 @@ func gasCallDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *St
return 0, errGasUintOverflow
}
- words, overflow := bigUint64(stack.Back(2))
+ words, overflow := vm.BigUint64(stack.Back(2))
if overflow {
return 0, errGasUintOverflow
}
- if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow {
+ if words, overflow = math.SafeMul(vm.ToWordSize(words), params.CopyGas); overflow {
return 0, errGasUintOverflow
}
@@ -89,7 +90,7 @@ func gasCallDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *St
return gas, nil
}
-func gasReturnDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasReturnDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
return 0, err
@@ -100,12 +101,12 @@ func gasReturnDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *
return 0, errGasUintOverflow
}
- words, overflow := bigUint64(stack.Back(2))
+ words, overflow := vm.BigUint64(stack.Back(2))
if overflow {
return 0, errGasUintOverflow
}
- if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow {
+ if words, overflow = math.SafeMul(vm.ToWordSize(words), params.CopyGas); overflow {
return 0, errGasUintOverflow
}
@@ -115,7 +116,7 @@ func gasReturnDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *
return gas, nil
}
-func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
var (
y, x = stack.Back(1), stack.Back(0)
current = evm.StateDB.GetState(contract.Address(), common.BigToHash(x))
@@ -185,8 +186,8 @@ func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, m
}
func makeGasLog(n uint64) gasFunc {
- return func(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- requestedSize, overflow := bigUint64(stack.Back(1))
+ return func(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+ requestedSize, overflow := vm.BigUint64(stack.Back(1))
if overflow {
return 0, errGasUintOverflow
}
@@ -214,7 +215,7 @@ func makeGasLog(n uint64) gasFunc {
}
}
-func gasSha3(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasSha3(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
var overflow bool
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
@@ -225,11 +226,11 @@ func gasSha3(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem
return 0, errGasUintOverflow
}
- wordGas, overflow := bigUint64(stack.Back(1))
+ wordGas, overflow := vm.BigUint64(stack.Back(1))
if overflow {
return 0, errGasUintOverflow
}
- if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.Sha3WordGas); overflow {
+ if wordGas, overflow = math.SafeMul(vm.ToWordSize(wordGas), params.Sha3WordGas); overflow {
return 0, errGasUintOverflow
}
if gas, overflow = math.SafeAdd(gas, wordGas); overflow {
@@ -238,7 +239,7 @@ func gasSha3(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem
return gas, nil
}
-func gasCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
return 0, err
@@ -249,11 +250,11 @@ func gasCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack,
return 0, errGasUintOverflow
}
- wordGas, overflow := bigUint64(stack.Back(2))
+ wordGas, overflow := vm.BigUint64(stack.Back(2))
if overflow {
return 0, errGasUintOverflow
}
- if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.CopyGas); overflow {
+ if wordGas, overflow = math.SafeMul(vm.ToWordSize(wordGas), params.CopyGas); overflow {
return 0, errGasUintOverflow
}
if gas, overflow = math.SafeAdd(gas, wordGas); overflow {
@@ -262,7 +263,7 @@ func gasCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack,
return gas, nil
}
-func gasExtCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasExtCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
return 0, err
@@ -273,12 +274,12 @@ func gasExtCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Sta
return 0, errGasUintOverflow
}
- wordGas, overflow := bigUint64(stack.Back(3))
+ wordGas, overflow := vm.BigUint64(stack.Back(3))
if overflow {
return 0, errGasUintOverflow
}
- if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.CopyGas); overflow {
+ if wordGas, overflow = math.SafeMul(vm.ToWordSize(wordGas), params.CopyGas); overflow {
return 0, errGasUintOverflow
}
@@ -288,11 +289,11 @@ func gasExtCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Sta
return gas, nil
}
-func gasExtCodeHash(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasExtCodeHash(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
return gt.ExtcodeHash, nil
}
-func gasMLoad(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasMLoad(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
var overflow bool
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
@@ -304,7 +305,7 @@ func gasMLoad(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, me
return gas, nil
}
-func gasMStore8(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasMStore8(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
var overflow bool
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
@@ -316,7 +317,7 @@ func gasMStore8(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack,
return gas, nil
}
-func gasMStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasMStore(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
var overflow bool
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
@@ -328,7 +329,7 @@ func gasMStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, m
return gas, nil
}
-func gasCreate(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasCreate(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
var overflow bool
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
@@ -340,7 +341,7 @@ func gasCreate(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, m
return gas, nil
}
-func gasCreate2(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasCreate2(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
var overflow bool
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
@@ -349,11 +350,11 @@ func gasCreate2(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack,
if gas, overflow = math.SafeAdd(gas, params.Create2Gas); overflow {
return 0, errGasUintOverflow
}
- wordGas, overflow := bigUint64(stack.Back(2))
+ wordGas, overflow := vm.BigUint64(stack.Back(2))
if overflow {
return 0, errGasUintOverflow
}
- if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.Sha3WordGas); overflow {
+ if wordGas, overflow = math.SafeMul(vm.ToWordSize(wordGas), params.Sha3WordGas); overflow {
return 0, errGasUintOverflow
}
if gas, overflow = math.SafeAdd(gas, wordGas); overflow {
@@ -363,20 +364,20 @@ func gasCreate2(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack,
return gas, nil
}
-func gasBalance(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasBalance(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
return gt.Balance, nil
}
-func gasExtCodeSize(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasExtCodeSize(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
return gt.ExtcodeSize, nil
}
-func gasSLoad(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasSLoad(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
return gt.SLoad, nil
}
-func gasExp(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- expByteLen := uint64((stack.data[stack.len()-2].BitLen() + 7) / 8)
+func gasExp(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+ expByteLen := uint64((stack.Data[stack.Len()-2].BitLen() + 7) / 8)
var (
gas = expByteLen * gt.ExpByte // no overflow check required. Max is 256 * ExpByte gas
@@ -388,7 +389,7 @@ func gasExp(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem
return gas, nil
}
-func gasCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasCall(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
var (
gas = gt.Calls
transfersValue = stack.Back(2).Sign() != 0
@@ -424,7 +425,7 @@ func gasCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem
return gas, nil
}
-func gasCallCode(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasCallCode(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
gas := gt.Calls
if stack.Back(2).Sign() != 0 {
gas += params.CallValueTransferGas
@@ -448,15 +449,15 @@ func gasCallCode(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack,
return gas, nil
}
-func gasReturn(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasReturn(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
return memoryGasCost(mem, memorySize)
}
-func gasRevert(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasRevert(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
return memoryGasCost(mem, memorySize)
}
-func gasSuicide(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasSuicide(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
var gas uint64
// EIP150 homestead gas reprice fork:
if evm.ChainConfig().IsEIP150(evm.BlockNumber) {
@@ -482,7 +483,7 @@ func gasSuicide(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack,
return gas, nil
}
-func gasDelegateCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasDelegateCall(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
return 0, err
@@ -502,7 +503,7 @@ func gasDelegateCall(gt params.GasTable, evm *EVM, contract *Contract, stack *St
return gas, nil
}
-func gasStaticCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasStaticCall(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
return 0, err
@@ -522,14 +523,14 @@ func gasStaticCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stac
return gas, nil
}
-func gasPush(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasPush(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
return GasFastestStep, nil
}
-func gasSwap(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasSwap(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
return GasFastestStep, nil
}
-func gasDup(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
+func gasDup(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
return GasFastestStep, nil
}
diff --git a/core/vm/gas_table_test.go b/core/vm/evm/gas_table_test.go
index 1b91aee56..35a902c67 100644
--- a/core/vm/gas_table_test.go
+++ b/core/vm/evm/gas_table_test.go
@@ -14,14 +14,18 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package vm
+package evm
-import "testing"
+import (
+ "testing"
+
+ "github.com/dexon-foundation/dexon/core/vm"
+)
func TestMemoryGasCost(t *testing.T) {
//size := uint64(math.MaxUint64 - 64)
size := uint64(0xffffffffe0)
- v, err := memoryGasCost(&Memory{}, size)
+ v, err := memoryGasCost(&vm.Memory{}, size)
if err != nil {
t.Error("didn't expect error:", err)
}
@@ -29,7 +33,7 @@ func TestMemoryGasCost(t *testing.T) {
t.Errorf("Expected: 36028899963961341, got %d", v)
}
- _, err = memoryGasCost(&Memory{}, size+1)
+ _, err = memoryGasCost(&vm.Memory{}, size+1)
if err == nil {
t.Error("expected error")
}
diff --git a/core/vm/gen_structlog.go b/core/vm/evm/gen_structlog.go
index a3da8734f..600af4b52 100644
--- a/core/vm/gen_structlog.go
+++ b/core/vm/evm/gen_structlog.go
@@ -1,6 +1,6 @@
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
-package vm
+package evm
import (
"encoding/json"
diff --git a/core/vm/evm/governance.go b/core/vm/evm/governance.go
new file mode 100644
index 000000000..8b31d3a01
--- /dev/null
+++ b/core/vm/evm/governance.go
@@ -0,0 +1,2198 @@
+// Copyright 2018 The dexon-consensus Authors
+// This file is part of the dexon-consensus library.
+//
+// The dexon-consensus library is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation, either version 3 of the License,
+// or (at your option) any later version.
+//
+// The dexon-consensus library is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the dexon-consensus library. If not, see
+// <http://www.gnu.org/licenses/>.
+
+package evm
+
+import (
+ "bytes"
+ "errors"
+ "math/big"
+ "sort"
+ "strings"
+
+ "github.com/dexon-foundation/dexon/accounts/abi"
+ "github.com/dexon-foundation/dexon/common"
+ "github.com/dexon-foundation/dexon/core/types"
+ "github.com/dexon-foundation/dexon/crypto"
+ "github.com/dexon-foundation/dexon/params"
+ "github.com/dexon-foundation/dexon/rlp"
+
+ coreCommon "github.com/dexon-foundation/dexon-consensus/common"
+ "github.com/dexon-foundation/dexon-consensus/core"
+ coreCrypto "github.com/dexon-foundation/dexon-consensus/core/crypto"
+ coreUtils "github.com/dexon-foundation/dexon-consensus/core/utils"
+ "github.com/dexon-foundation/dexon/core/vm"
+
+ "github.com/dexon-foundation/dexon-consensus/core/crypto/ecdsa"
+ coreTypes "github.com/dexon-foundation/dexon-consensus/core/types"
+ dkgTypes "github.com/dexon-foundation/dexon-consensus/core/types/dkg"
+)
+
+var GovernanceContractAddress = common.HexToAddress("63751838d6485578b23e8b051d40861ecc416794")
+
+var abiObject abi.ABI
+var GovernanceContractName2Method map[string]abi.Method
+var sig2Method map[string]abi.Method
+var events map[string]abi.Event
+
+type Bytes32 [32]byte
+
+type ReportType uint64
+
+const (
+ ReportTypeInvalidDKG = iota
+ ReportTypeForkVote
+ ReportTypeForkBlock
+)
+
+func init() {
+ var err error
+
+ // Parse governance contract ABI.
+ abiObject, err = abi.JSON(strings.NewReader(GovernanceABIJSON))
+ if err != nil {
+ panic(err)
+ }
+
+ sig2Method = make(map[string]abi.Method)
+ GovernanceContractName2Method = make(map[string]abi.Method)
+
+ // Construct dispatch table.
+ for _, method := range abiObject.Methods {
+ sig2Method[string(method.Id())] = method
+ GovernanceContractName2Method[method.Name] = method
+ }
+
+ events = make(map[string]abi.Event)
+
+ // Event cache.
+ for _, event := range abiObject.Events {
+ events[event.Name] = event
+ }
+}
+
+// RunGovernanceContract executes governance contract.
+func RunGovernanceContract(evm *EVM, input []byte, contract *Contract) (ret []byte, err error) {
+ if len(input) < 4 {
+ return nil, nil
+ }
+
+ // Parse input.
+ method, exists := sig2Method[string(input[:4])]
+ if !exists {
+ return nil, errExecutionReverted
+ }
+
+ // Dispatch method call.
+ g := newGovernanceContract(evm, contract)
+ arguments := input[4:]
+
+ switch method.Name {
+ case "addDKGComplaint":
+ args := struct {
+ Round *big.Int
+ Complaint []byte
+ }{}
+ if err := method.Inputs.Unpack(&args, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ return g.addDKGComplaint(args.Round, args.Complaint)
+ case "addDKGMasterPublicKey":
+ args := struct {
+ Round *big.Int
+ PublicKey []byte
+ }{}
+ if err := method.Inputs.Unpack(&args, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ return g.addDKGMasterPublicKey(args.Round, args.PublicKey)
+ case "addDKGMPKReady":
+ args := struct {
+ Round *big.Int
+ MPKReady []byte
+ }{}
+ if err := method.Inputs.Unpack(&args, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ return g.addDKGMPKReady(args.Round, args.MPKReady)
+ case "addDKGFinalize":
+ args := struct {
+ Round *big.Int
+ Finalize []byte
+ }{}
+ if err := method.Inputs.Unpack(&args, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ return g.addDKGFinalize(args.Round, args.Finalize)
+ case "delegate":
+ address := common.Address{}
+ if err := method.Inputs.Unpack(&address, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ return g.delegate(address)
+ case "delegatorsLength":
+ address := common.Address{}
+ if err := method.Inputs.Unpack(&address, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ res, err := method.Outputs.Pack(g.state.LenDelegators(address))
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "nodesLength":
+ res, err := method.Outputs.Pack(g.state.LenNodes())
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "payFine":
+ address := common.Address{}
+ if err := method.Inputs.Unpack(&address, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ return g.payFine(address)
+ case "proposeCRS":
+ args := struct {
+ Round *big.Int
+ SignedCRS []byte
+ }{}
+ if err := method.Inputs.Unpack(&args, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ return g.proposeCRS(args.Round, args.SignedCRS)
+ case "report":
+ args := struct {
+ Type *big.Int
+ Arg1 []byte
+ Arg2 []byte
+ }{}
+ if err := method.Inputs.Unpack(&args, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ return g.report(args.Type, args.Arg1, args.Arg2)
+ case "stake":
+ args := struct {
+ PublicKey []byte
+ Name string
+ Email string
+ Location string
+ Url string
+ }{}
+ if err := method.Inputs.Unpack(&args, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ return g.stake(args.PublicKey, args.Name, args.Email, args.Location, args.Url)
+ case "snapshotRound":
+ args := struct {
+ Round *big.Int
+ Height *big.Int
+ }{}
+ if err := method.Inputs.Unpack(&args, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ return g.snapshotRound(args.Round, args.Height)
+ case "transferOwnership":
+ var newOwner common.Address
+ if err := method.Inputs.Unpack(&newOwner, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ return g.transferOwnership(newOwner)
+ case "undelegate":
+ address := common.Address{}
+ if err := method.Inputs.Unpack(&address, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ return g.undelegate(address)
+ case "unstake":
+ return g.unstake()
+ case "updateConfiguration":
+ var cfg rawConfigStruct
+ if err := method.Inputs.Unpack(&cfg, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ return g.updateConfiguration(&cfg)
+ case "withdraw":
+ address := common.Address{}
+ if err := method.Inputs.Unpack(&address, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ return g.withdraw(address)
+
+ // --------------------------------
+ // Solidity auto generated methods.
+ // --------------------------------
+
+ case "blockGasLimit":
+ res, err := method.Outputs.Pack(g.state.BlockGasLimit())
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "crs":
+ round := new(big.Int)
+ if err := method.Inputs.Unpack(&round, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ res, err := method.Outputs.Pack(g.state.CRS(round))
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "delegators":
+ nodeAddr, index := common.Address{}, new(big.Int)
+ args := []interface{}{&nodeAddr, &index}
+ if err := method.Inputs.Unpack(&args, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ delegator := g.state.Delegator(nodeAddr, index)
+ res, err := method.Outputs.Pack(delegator.Owner, delegator.Value, delegator.UndelegatedAt)
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "delegatorsOffset":
+ nodeAddr, delegatorAddr := common.Address{}, common.Address{}
+ args := []interface{}{&nodeAddr, &delegatorAddr}
+ if err := method.Inputs.Unpack(&args, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ res, err := method.Outputs.Pack(g.state.DelegatorsOffset(nodeAddr, delegatorAddr))
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "dkgComplaints":
+ round, index := new(big.Int), new(big.Int)
+ args := []interface{}{&round, &index}
+ if err := method.Inputs.Unpack(&args, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ complaints := g.state.DKGComplaints(round)
+ if int(index.Uint64()) >= len(complaints) {
+ return nil, errExecutionReverted
+ }
+ complaint := complaints[index.Uint64()]
+ res, err := method.Outputs.Pack(complaint)
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "dkgReadys":
+ round, addr := new(big.Int), common.Address{}
+ args := []interface{}{&round, &addr}
+ if err := method.Inputs.Unpack(&args, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ ready := g.state.DKGMPKReady(round, addr)
+ res, err := method.Outputs.Pack(ready)
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "dkgReadysCount":
+ round := new(big.Int)
+ if err := method.Inputs.Unpack(&round, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ count := g.state.DKGMPKReadysCount(round)
+ res, err := method.Outputs.Pack(count)
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+
+ case "dkgFinalizeds":
+ round, addr := new(big.Int), common.Address{}
+ args := []interface{}{&round, &addr}
+ if err := method.Inputs.Unpack(&args, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ finalized := g.state.DKGFinalized(round, addr)
+ res, err := method.Outputs.Pack(finalized)
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "dkgFinalizedsCount":
+ round := new(big.Int)
+ if err := method.Inputs.Unpack(&round, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ count := g.state.DKGFinalizedsCount(round)
+ res, err := method.Outputs.Pack(count)
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "dkgMasterPublicKeys":
+ round, index := new(big.Int), new(big.Int)
+ args := []interface{}{&round, &index}
+ if err := method.Inputs.Unpack(&args, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ mpks := g.state.DKGMasterPublicKeys(round)
+ if int(index.Uint64()) >= len(mpks) {
+ return nil, errExecutionReverted
+ }
+ mpk := mpks[index.Uint64()]
+ res, err := method.Outputs.Pack(mpk)
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "dkgSetSize":
+ res, err := method.Outputs.Pack(g.state.DKGSetSize())
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "finedRecords":
+ record := Bytes32{}
+ if err := method.Inputs.Unpack(&record, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ value := g.state.FineRecords(record)
+ res, err := method.Outputs.Pack(value)
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "fineValues":
+ index := new(big.Int)
+ if err := method.Inputs.Unpack(&index, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ value := g.state.FineValue(index)
+ res, err := method.Outputs.Pack(value)
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "k":
+ res, err := method.Outputs.Pack(g.state.K())
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "lambdaBA":
+ res, err := method.Outputs.Pack(g.state.LambdaBA())
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "lambdaDKG":
+ res, err := method.Outputs.Pack(g.state.LambdaDKG())
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "lastHalvedAmount":
+ res, err := method.Outputs.Pack(g.state.LastHalvedAmount())
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "lockupPeriod":
+ res, err := method.Outputs.Pack(g.state.LockupPeriod())
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "minBlockInterval":
+ res, err := method.Outputs.Pack(g.state.MinBlockInterval())
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "miningVelocity":
+ res, err := method.Outputs.Pack(g.state.MiningVelocity())
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "minStake":
+ res, err := method.Outputs.Pack(g.state.MinStake())
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "nextHalvingSupply":
+ res, err := method.Outputs.Pack(g.state.NextHalvingSupply())
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "numChains":
+ res, err := method.Outputs.Pack(g.state.NumChains())
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "nodes":
+ index := new(big.Int)
+ if err := method.Inputs.Unpack(&index, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ info := g.state.Node(index)
+ res, err := method.Outputs.Pack(
+ info.Owner, info.PublicKey, info.Staked, info.Fined,
+ info.Name, info.Email, info.Location, info.Url)
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "nodesOffsetByAddress":
+ address := common.Address{}
+ if err := method.Inputs.Unpack(&address, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ res, err := method.Outputs.Pack(g.state.NodesOffsetByAddress(address))
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "nodesOffsetByID":
+ var id Bytes32
+ if err := method.Inputs.Unpack(&id, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ res, err := method.Outputs.Pack(g.state.NodesOffsetByID(id))
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "notarySetSize":
+ res, err := method.Outputs.Pack(g.state.NotarySetSize())
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "owner":
+ res, err := method.Outputs.Pack(g.state.Owner())
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "phiRatio":
+ res, err := method.Outputs.Pack(g.state.PhiRatio())
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "roundHeight":
+ round := new(big.Int)
+ if err := method.Inputs.Unpack(&round, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ res, err := method.Outputs.Pack(g.state.RoundHeight(round))
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "roundInterval":
+ res, err := method.Outputs.Pack(g.state.RoundInterval())
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "totalStaked":
+ res, err := method.Outputs.Pack(g.state.TotalStaked())
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "totalSupply":
+ res, err := method.Outputs.Pack(g.state.TotalSupply())
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ }
+ return nil, errExecutionReverted
+}
+
+// Storage position enums.
+const (
+ roundHeightLoc = iota
+ totalSupplyLoc
+ totalStakedLoc
+ nodesLoc
+ nodesOffsetByAddressLoc
+ nodesOffsetByIDLoc
+ delegatorsLoc
+ delegatorsOffsetLoc
+ crsLoc
+ dkgMasterPublicKeysLoc
+ dkgComplaintsLoc
+ dkgReadyLoc
+ dkgReadysCountLoc
+ dkgFinalizedLoc
+ dkgFinalizedsCountLoc
+ ownerLoc
+ minStakeLoc
+ lockupPeriodLoc
+ miningVelocityLoc
+ nextHalvingSupplyLoc
+ lastHalvedAmountLoc
+ blockGasLimitLoc
+ numChainsLoc
+ lambdaBALoc
+ lambdaDKGLoc
+ kLoc
+ phiRatioLoc
+ notarySetSizeLoc
+ dkgSetSizeLoc
+ roundIntervalLoc
+ minBlockIntervalLoc
+ fineValuesLoc
+ finedRecordsLoc
+)
+
+func publicKeyToNodeID(pkBytes []byte) (Bytes32, error) {
+ pk, err := crypto.UnmarshalPubkey(pkBytes)
+ if err != nil {
+ return Bytes32{}, err
+ }
+ id := Bytes32(coreTypes.NewNodeID(ecdsa.NewPublicKeyFromECDSA(pk)).Hash)
+ return id, nil
+}
+
+// State manipulation helper fro the governance contract.
+type GovernanceStateHelper struct {
+ StateDB StateDB
+}
+
+func (s *GovernanceStateHelper) getState(loc common.Hash) common.Hash {
+ return s.StateDB.GetState(GovernanceContractAddress, loc)
+}
+
+func (s *GovernanceStateHelper) setState(loc common.Hash, val common.Hash) {
+ s.StateDB.SetState(GovernanceContractAddress, loc, val)
+}
+
+func (s *GovernanceStateHelper) getStateBigInt(loc *big.Int) *big.Int {
+ res := s.StateDB.GetState(GovernanceContractAddress, common.BigToHash(loc))
+ return new(big.Int).SetBytes(res.Bytes())
+}
+
+func (s *GovernanceStateHelper) setStateBigInt(loc *big.Int, val *big.Int) {
+ s.setState(common.BigToHash(loc), common.BigToHash(val))
+}
+
+func (s *GovernanceStateHelper) getSlotLoc(loc *big.Int) *big.Int {
+ return new(big.Int).SetBytes(crypto.Keccak256(common.BigToHash(loc).Bytes()))
+}
+
+func (s *GovernanceStateHelper) getMapLoc(pos *big.Int, key []byte) *big.Int {
+ return new(big.Int).SetBytes(crypto.Keccak256(key, common.BigToHash(pos).Bytes()))
+}
+
+func (s *GovernanceStateHelper) readBytes(loc *big.Int) []byte {
+ // Length of the dynamic array (bytes).
+ rawLength := s.getStateBigInt(loc)
+ lengthByte := new(big.Int).Mod(rawLength, big.NewInt(256))
+
+ // Bytes length <= 31, lengthByte % 2 == 0
+ // return the high 31 bytes.
+ if new(big.Int).Mod(lengthByte, big.NewInt(2)).Cmp(big.NewInt(0)) == 0 {
+ length := new(big.Int).Div(lengthByte, big.NewInt(2)).Uint64()
+ return rawLength.Bytes()[:length]
+ }
+
+ // Actual length = (rawLength - 1) / 2
+ length := new(big.Int).Div(new(big.Int).Sub(rawLength, big.NewInt(1)), big.NewInt(2)).Uint64()
+
+ // Data address.
+ dataLoc := s.getSlotLoc(loc)
+
+ // Read continuously for length bytes.
+ carry := int64(0)
+ if length%32 > 0 {
+ carry = 1
+ }
+ chunks := int64(length/32) + carry
+ var data []byte
+ for i := int64(0); i < chunks; i++ {
+ loc = new(big.Int).Add(dataLoc, big.NewInt(i))
+ data = append(data, s.getState(common.BigToHash(loc)).Bytes()...)
+ }
+ data = data[:length]
+ return data
+}
+
+func (s *GovernanceStateHelper) writeBytes(loc *big.Int, data []byte) {
+ length := int64(len(data))
+
+ if length == 0 {
+ s.setState(common.BigToHash(loc), common.Hash{})
+ return
+ }
+
+ // Short bytes (length <= 31).
+ if length < 32 {
+ data2 := append([]byte(nil), data...)
+ // Right pad with zeros
+ for len(data2) < 31 {
+ data2 = append(data2, byte(0))
+ }
+ data2 = append(data2, byte(length*2))
+ s.setState(common.BigToHash(loc), common.BytesToHash(data2))
+ return
+ }
+
+ // Write 2 * length + 1.
+ storedLength := new(big.Int).Add(new(big.Int).Mul(
+ big.NewInt(length), big.NewInt(2)), big.NewInt(1))
+ s.setStateBigInt(loc, storedLength)
+ // Write data chunck.
+ dataLoc := s.getSlotLoc(loc)
+ carry := int64(0)
+ if length%32 > 0 {
+ carry = 1
+ }
+ chunks := length/32 + carry
+ for i := int64(0); i < chunks; i++ {
+ loc = new(big.Int).Add(dataLoc, big.NewInt(i))
+ maxLoc := (i + 1) * 32
+ if maxLoc > length {
+ maxLoc = length
+ }
+ data2 := data[i*32 : maxLoc]
+ // Right pad with zeros.
+ for len(data2) < 32 {
+ data2 = append(data2, byte(0))
+ }
+ s.setState(common.BigToHash(loc), common.BytesToHash(data2))
+ }
+}
+
+func (s *GovernanceStateHelper) read2DByteArray(pos, index *big.Int) [][]byte {
+ baseLoc := s.getSlotLoc(pos)
+ loc := new(big.Int).Add(baseLoc, index)
+
+ arrayLength := s.getStateBigInt(loc)
+ dataLoc := s.getSlotLoc(loc)
+
+ data := [][]byte{}
+ for i := int64(0); i < int64(arrayLength.Uint64()); i++ {
+ elementLoc := new(big.Int).Add(dataLoc, big.NewInt(i))
+ data = append(data, s.readBytes(elementLoc))
+ }
+
+ return data
+}
+func (s *GovernanceStateHelper) appendTo2DByteArray(pos, index *big.Int, data []byte) {
+ // Find the loc of the last element.
+ baseLoc := s.getSlotLoc(pos)
+ loc := new(big.Int).Add(baseLoc, index)
+
+ // Increase length by 1.
+ arrayLength := s.getStateBigInt(loc)
+ s.setStateBigInt(loc, new(big.Int).Add(arrayLength, big.NewInt(1)))
+
+ // Write element.
+ dataLoc := s.getSlotLoc(loc)
+ elementLoc := new(big.Int).Add(dataLoc, arrayLength)
+ s.writeBytes(elementLoc, data)
+}
+
+// uint256[] public roundHeight;
+func (s *GovernanceStateHelper) LenRoundHeight() *big.Int {
+ return s.getStateBigInt(big.NewInt(roundHeightLoc))
+}
+func (s *GovernanceStateHelper) RoundHeight(round *big.Int) *big.Int {
+ baseLoc := s.getSlotLoc(big.NewInt(roundHeightLoc))
+ loc := new(big.Int).Add(baseLoc, round)
+ return s.getStateBigInt(loc)
+}
+func (s *GovernanceStateHelper) PushRoundHeight(height *big.Int) {
+ // Increase length by 1.
+ length := s.getStateBigInt(big.NewInt(roundHeightLoc))
+ s.setStateBigInt(big.NewInt(roundHeightLoc), new(big.Int).Add(length, big.NewInt(1)))
+
+ baseLoc := s.getSlotLoc(big.NewInt(roundHeightLoc))
+ loc := new(big.Int).Add(baseLoc, length)
+
+ s.setStateBigInt(loc, height)
+}
+
+// uint256 public totalSupply;
+func (s *GovernanceStateHelper) TotalSupply() *big.Int {
+ return s.getStateBigInt(big.NewInt(totalSupplyLoc))
+}
+func (s *GovernanceStateHelper) IncTotalSupply(amount *big.Int) {
+ s.setStateBigInt(big.NewInt(totalSupplyLoc), new(big.Int).Add(s.TotalSupply(), amount))
+}
+func (s *GovernanceStateHelper) DecTotalSupply(amount *big.Int) {
+ s.setStateBigInt(big.NewInt(totalSupplyLoc), new(big.Int).Sub(s.TotalSupply(), amount))
+}
+
+// uint256 public totalStaked;
+func (s *GovernanceStateHelper) TotalStaked() *big.Int {
+ return s.getStateBigInt(big.NewInt(totalStakedLoc))
+}
+func (s *GovernanceStateHelper) IncTotalStaked(amount *big.Int) {
+ s.setStateBigInt(big.NewInt(totalStakedLoc), new(big.Int).Add(s.TotalStaked(), amount))
+}
+func (s *GovernanceStateHelper) DecTotalStaked(amount *big.Int) {
+ s.setStateBigInt(big.NewInt(totalStakedLoc), new(big.Int).Sub(s.TotalStaked(), amount))
+}
+
+// struct Node {
+// address owner;
+// bytes publicKey;
+// uint256 staked;
+// uint256 fined;
+// string name;
+// string email;
+// string location;
+// string url;
+// }
+//
+// Node[] nodes;
+
+type nodeInfo struct {
+ Owner common.Address
+ PublicKey []byte
+ Staked *big.Int
+ Fined *big.Int
+ Name string
+ Email string
+ Location string
+ Url string
+}
+
+const nodeStructSize = 8
+
+func (s *GovernanceStateHelper) LenNodes() *big.Int {
+ return s.getStateBigInt(big.NewInt(nodesLoc))
+}
+func (s *GovernanceStateHelper) Node(index *big.Int) *nodeInfo {
+ node := new(nodeInfo)
+
+ arrayBaseLoc := s.getSlotLoc(big.NewInt(nodesLoc))
+ elementBaseLoc := new(big.Int).Add(arrayBaseLoc,
+ new(big.Int).Mul(index, big.NewInt(nodeStructSize)))
+
+ // Owner.
+ loc := elementBaseLoc
+ node.Owner = common.BytesToAddress(s.getState(common.BigToHash(elementBaseLoc)).Bytes())
+
+ // PublicKey.
+ loc = new(big.Int).Add(elementBaseLoc, big.NewInt(1))
+ node.PublicKey = s.readBytes(loc)
+
+ // Staked.
+ loc = new(big.Int).Add(elementBaseLoc, big.NewInt(2))
+ node.Staked = s.getStateBigInt(loc)
+
+ // Fined.
+ loc = new(big.Int).Add(elementBaseLoc, big.NewInt(3))
+ node.Fined = s.getStateBigInt(loc)
+
+ // Name.
+ loc = new(big.Int).Add(elementBaseLoc, big.NewInt(4))
+ node.Name = string(s.readBytes(loc))
+
+ // Email.
+ loc = new(big.Int).Add(elementBaseLoc, big.NewInt(5))
+ node.Email = string(s.readBytes(loc))
+
+ // Location.
+ loc = new(big.Int).Add(elementBaseLoc, big.NewInt(6))
+ node.Location = string(s.readBytes(loc))
+
+ // Url.
+ loc = new(big.Int).Add(elementBaseLoc, big.NewInt(7))
+ node.Url = string(s.readBytes(loc))
+
+ return node
+}
+func (s *GovernanceStateHelper) PushNode(n *nodeInfo) {
+ // Increase length by 1.
+ arrayLength := s.LenNodes()
+ s.setStateBigInt(big.NewInt(nodesLoc), new(big.Int).Add(arrayLength, big.NewInt(1)))
+
+ s.UpdateNode(arrayLength, n)
+}
+func (s *GovernanceStateHelper) UpdateNode(index *big.Int, n *nodeInfo) {
+ arrayBaseLoc := s.getSlotLoc(big.NewInt(nodesLoc))
+ elementBaseLoc := new(big.Int).Add(arrayBaseLoc,
+ new(big.Int).Mul(index, big.NewInt(nodeStructSize)))
+
+ // Owner.
+ loc := elementBaseLoc
+ s.setState(common.BigToHash(loc), n.Owner.Hash())
+
+ // PublicKey.
+ loc = new(big.Int).Add(elementBaseLoc, big.NewInt(1))
+ s.writeBytes(loc, n.PublicKey)
+
+ // Staked.
+ loc = new(big.Int).Add(elementBaseLoc, big.NewInt(2))
+ s.setStateBigInt(loc, n.Staked)
+
+ // Fined.
+ loc = new(big.Int).Add(elementBaseLoc, big.NewInt(3))
+ s.setStateBigInt(loc, n.Fined)
+
+ // Name.
+ loc = new(big.Int).Add(elementBaseLoc, big.NewInt(4))
+ s.writeBytes(loc, []byte(n.Name))
+
+ // Email.
+ loc = new(big.Int).Add(elementBaseLoc, big.NewInt(5))
+ s.writeBytes(loc, []byte(n.Email))
+
+ // Location.
+ loc = new(big.Int).Add(elementBaseLoc, big.NewInt(6))
+ s.writeBytes(loc, []byte(n.Location))
+
+ // Url.
+ loc = new(big.Int).Add(elementBaseLoc, big.NewInt(7))
+ s.writeBytes(loc, []byte(n.Url))
+}
+func (s *GovernanceStateHelper) PopLastNode() {
+ // Decrease length by 1.
+ arrayLength := s.LenNodes()
+ newArrayLength := new(big.Int).Sub(arrayLength, big.NewInt(1))
+ s.setStateBigInt(big.NewInt(nodesLoc), newArrayLength)
+
+ s.UpdateNode(newArrayLength, &nodeInfo{
+ Staked: big.NewInt(0),
+ Fined: big.NewInt(0),
+ })
+}
+func (s *GovernanceStateHelper) Nodes() []*nodeInfo {
+ var nodes []*nodeInfo
+ for i := int64(0); i < int64(s.LenNodes().Uint64()); i++ {
+ nodes = append(nodes, s.Node(big.NewInt(i)))
+ }
+ return nodes
+}
+func (s *GovernanceStateHelper) QualifiedNodes() []*nodeInfo {
+ var nodes []*nodeInfo
+ for i := int64(0); i < int64(s.LenNodes().Uint64()); i++ {
+ node := s.Node(big.NewInt(i))
+ if new(big.Int).Sub(node.Staked, node.Fined).Cmp(s.MinStake()) >= 0 {
+ nodes = append(nodes, node)
+ }
+ }
+ return nodes
+}
+
+// mapping(address => uint256) public nodeOffsetByAddress;
+func (s *GovernanceStateHelper) NodesOffsetByAddress(addr common.Address) *big.Int {
+ loc := s.getMapLoc(big.NewInt(nodesOffsetByAddressLoc), addr.Bytes())
+ return new(big.Int).Sub(s.getStateBigInt(loc), big.NewInt(1))
+}
+func (s *GovernanceStateHelper) PutNodesOffsetByAddress(addr common.Address, offset *big.Int) {
+ loc := s.getMapLoc(big.NewInt(nodesOffsetByAddressLoc), addr.Bytes())
+ s.setStateBigInt(loc, new(big.Int).Add(offset, big.NewInt(1)))
+}
+func (s *GovernanceStateHelper) DeleteNodesOffsetByAddress(addr common.Address) {
+ loc := s.getMapLoc(big.NewInt(nodesOffsetByAddressLoc), addr.Bytes())
+ s.setStateBigInt(loc, big.NewInt(0))
+}
+
+// mapping(address => uint256) public nodeOffsetByID;
+func (s *GovernanceStateHelper) NodesOffsetByID(id Bytes32) *big.Int {
+ loc := s.getMapLoc(big.NewInt(nodesOffsetByIDLoc), id[:])
+ return new(big.Int).Sub(s.getStateBigInt(loc), big.NewInt(1))
+}
+func (s *GovernanceStateHelper) PutNodesOffsetByID(id Bytes32, offset *big.Int) {
+ loc := s.getMapLoc(big.NewInt(nodesOffsetByIDLoc), id[:])
+ s.setStateBigInt(loc, new(big.Int).Add(offset, big.NewInt(1)))
+}
+func (s *GovernanceStateHelper) DeleteNodesOffsetByID(id Bytes32) {
+ loc := s.getMapLoc(big.NewInt(nodesOffsetByIDLoc), id[:])
+ s.setStateBigInt(loc, big.NewInt(0))
+}
+
+func (s *GovernanceStateHelper) PutNodeOffsets(n *nodeInfo, offset *big.Int) error {
+ id, err := publicKeyToNodeID(n.PublicKey)
+ if err != nil {
+ return err
+ }
+ s.PutNodesOffsetByID(id, offset)
+ s.PutNodesOffsetByAddress(n.Owner, offset)
+ return nil
+}
+
+// struct Delegator {
+// address node;
+// address owner;
+// uint256 value;
+// uint256 undelegated_at;
+// }
+
+type delegatorInfo struct {
+ Owner common.Address
+ Value *big.Int
+ UndelegatedAt *big.Int
+}
+
+const delegatorStructSize = 3
+
+// mapping(address => Delegator[]) public delegators;
+func (s *GovernanceStateHelper) LenDelegators(nodeAddr common.Address) *big.Int {
+ loc := s.getMapLoc(big.NewInt(delegatorsLoc), nodeAddr.Bytes())
+ return s.getStateBigInt(loc)
+}
+func (s *GovernanceStateHelper) Delegator(nodeAddr common.Address, offset *big.Int) *delegatorInfo {
+ delegator := new(delegatorInfo)
+
+ loc := s.getMapLoc(big.NewInt(delegatorsLoc), nodeAddr.Bytes())
+ arrayBaseLoc := s.getSlotLoc(loc)
+ elementBaseLoc := new(big.Int).Add(arrayBaseLoc, new(big.Int).Mul(big.NewInt(delegatorStructSize), offset))
+
+ // Owner.
+ loc = elementBaseLoc
+ delegator.Owner = common.BytesToAddress(s.getState(common.BigToHash(elementBaseLoc)).Bytes())
+
+ // Value.
+ loc = new(big.Int).Add(elementBaseLoc, big.NewInt(1))
+ delegator.Value = s.getStateBigInt(loc)
+
+ // UndelegatedAt.
+ loc = new(big.Int).Add(elementBaseLoc, big.NewInt(2))
+ delegator.UndelegatedAt = s.getStateBigInt(loc)
+
+ return delegator
+}
+func (s *GovernanceStateHelper) PushDelegator(nodeAddr common.Address, delegator *delegatorInfo) {
+ // Increase length by 1.
+ arrayLength := s.LenDelegators(nodeAddr)
+ loc := s.getMapLoc(big.NewInt(delegatorsLoc), nodeAddr.Bytes())
+ s.setStateBigInt(loc, new(big.Int).Add(arrayLength, big.NewInt(1)))
+
+ s.UpdateDelegator(nodeAddr, arrayLength, delegator)
+}
+func (s *GovernanceStateHelper) UpdateDelegator(nodeAddr common.Address, offset *big.Int, delegator *delegatorInfo) {
+ loc := s.getMapLoc(big.NewInt(delegatorsLoc), nodeAddr.Bytes())
+ arrayBaseLoc := s.getSlotLoc(loc)
+ elementBaseLoc := new(big.Int).Add(arrayBaseLoc, new(big.Int).Mul(big.NewInt(delegatorStructSize), offset))
+
+ // Owner.
+ loc = elementBaseLoc
+ s.setState(common.BigToHash(loc), delegator.Owner.Hash())
+
+ // Value.
+ loc = new(big.Int).Add(elementBaseLoc, big.NewInt(1))
+ s.setStateBigInt(loc, delegator.Value)
+
+ // UndelegatedAt.
+ loc = new(big.Int).Add(elementBaseLoc, big.NewInt(2))
+ s.setStateBigInt(loc, delegator.UndelegatedAt)
+}
+func (s *GovernanceStateHelper) PopLastDelegator(nodeAddr common.Address) {
+ // Decrease length by 1.
+ arrayLength := s.LenDelegators(nodeAddr)
+ newArrayLength := new(big.Int).Sub(arrayLength, big.NewInt(1))
+ loc := s.getMapLoc(big.NewInt(delegatorsLoc), nodeAddr.Bytes())
+ s.setStateBigInt(loc, newArrayLength)
+
+ s.UpdateDelegator(nodeAddr, newArrayLength, &delegatorInfo{
+ Value: big.NewInt(0),
+ UndelegatedAt: big.NewInt(0),
+ })
+}
+
+// mapping(address => mapping(address => uint256)) delegatorsOffset;
+func (s *GovernanceStateHelper) DelegatorsOffset(nodeAddr, delegatorAddr common.Address) *big.Int {
+ loc := s.getMapLoc(s.getMapLoc(big.NewInt(delegatorsOffsetLoc), nodeAddr.Bytes()), delegatorAddr.Bytes())
+ return new(big.Int).Sub(s.getStateBigInt(loc), big.NewInt(1))
+}
+func (s *GovernanceStateHelper) PutDelegatorOffset(nodeAddr, delegatorAddr common.Address, offset *big.Int) {
+ loc := s.getMapLoc(s.getMapLoc(big.NewInt(delegatorsOffsetLoc), nodeAddr.Bytes()), delegatorAddr.Bytes())
+ s.setStateBigInt(loc, new(big.Int).Add(offset, big.NewInt(1)))
+}
+func (s *GovernanceStateHelper) DeleteDelegatorsOffset(nodeAddr, delegatorAddr common.Address) {
+ loc := s.getMapLoc(s.getMapLoc(big.NewInt(delegatorsOffsetLoc), nodeAddr.Bytes()), delegatorAddr.Bytes())
+ s.setStateBigInt(loc, big.NewInt(0))
+}
+
+// bytes32[] public crs;
+func (s *GovernanceStateHelper) LenCRS() *big.Int {
+ return s.getStateBigInt(big.NewInt(crsLoc))
+}
+func (s *GovernanceStateHelper) CRS(index *big.Int) common.Hash {
+ baseLoc := s.getSlotLoc(big.NewInt(crsLoc))
+ loc := new(big.Int).Add(baseLoc, index)
+ return s.getState(common.BigToHash(loc))
+}
+func (s *GovernanceStateHelper) CurrentCRS() common.Hash {
+ return s.CRS(new(big.Int).Sub(s.LenCRS(), big.NewInt(1)))
+}
+func (s *GovernanceStateHelper) PushCRS(crs common.Hash) {
+ // increase length by 1.
+ length := s.getStateBigInt(big.NewInt(crsLoc))
+ s.setStateBigInt(big.NewInt(crsLoc), new(big.Int).Add(length, big.NewInt(1)))
+
+ baseLoc := s.getSlotLoc(big.NewInt(crsLoc))
+ loc := new(big.Int).Add(baseLoc, length)
+
+ s.setState(common.BigToHash(loc), crs)
+}
+func (s *GovernanceStateHelper) Round() *big.Int {
+ return new(big.Int).Sub(s.getStateBigInt(big.NewInt(crsLoc)), big.NewInt(1))
+}
+
+// bytes[][] public dkgMasterPublicKeys;
+func (s *GovernanceStateHelper) DKGMasterPublicKeys(round *big.Int) [][]byte {
+ return s.read2DByteArray(big.NewInt(dkgMasterPublicKeysLoc), round)
+}
+func (s *GovernanceStateHelper) PushDKGMasterPublicKey(round *big.Int, mpk []byte) {
+ s.appendTo2DByteArray(big.NewInt(dkgMasterPublicKeysLoc), round, mpk)
+}
+func (s *GovernanceStateHelper) UniqueDKGMasterPublicKeys(round *big.Int) []*dkgTypes.MasterPublicKey {
+ // Prepare DKGMasterPublicKeys.
+ var dkgMasterPKs []*dkgTypes.MasterPublicKey
+ existence := make(map[coreTypes.NodeID]struct{})
+ for _, mpk := range s.DKGMasterPublicKeys(round) {
+ x := new(dkgTypes.MasterPublicKey)
+ if err := rlp.DecodeBytes(mpk, x); err != nil {
+ panic(err)
+ }
+
+ // Only the first DKG MPK submission is valid.
+ if _, exists := existence[x.ProposerID]; exists {
+ continue
+ }
+ existence[x.ProposerID] = struct{}{}
+ dkgMasterPKs = append(dkgMasterPKs, x)
+ }
+ return dkgMasterPKs
+}
+func (s *GovernanceStateHelper) GetDKGMasterPublicKeyByProposerID(
+ round *big.Int, proposerID coreTypes.NodeID) (*dkgTypes.MasterPublicKey, error) {
+
+ for _, mpk := range s.DKGMasterPublicKeys(round) {
+ x := new(dkgTypes.MasterPublicKey)
+ if err := rlp.DecodeBytes(mpk, x); err != nil {
+ panic(err)
+ }
+ if x.ProposerID.Equal(proposerID) {
+ return x, nil
+ }
+ }
+ return nil, errors.New("not found")
+}
+
+// bytes[][] public dkgComplaints;
+func (s *GovernanceStateHelper) DKGComplaints(round *big.Int) [][]byte {
+ return s.read2DByteArray(big.NewInt(dkgComplaintsLoc), round)
+}
+func (s *GovernanceStateHelper) PushDKGComplaint(round *big.Int, complaint []byte) {
+ s.appendTo2DByteArray(big.NewInt(dkgComplaintsLoc), round, complaint)
+}
+
+// mapping(address => bool)[] public dkgReady;
+func (s *GovernanceStateHelper) DKGMPKReady(round *big.Int, addr common.Address) bool {
+ baseLoc := new(big.Int).Add(s.getSlotLoc(big.NewInt(dkgReadyLoc)), round)
+ mapLoc := s.getMapLoc(baseLoc, addr.Bytes())
+ return s.getStateBigInt(mapLoc).Cmp(big.NewInt(0)) != 0
+}
+func (s *GovernanceStateHelper) PutDKGMPKReady(round *big.Int, addr common.Address, ready bool) {
+ baseLoc := new(big.Int).Add(s.getSlotLoc(big.NewInt(dkgReadyLoc)), round)
+ mapLoc := s.getMapLoc(baseLoc, addr.Bytes())
+ res := big.NewInt(0)
+ if ready {
+ res = big.NewInt(1)
+ }
+ s.setStateBigInt(mapLoc, res)
+}
+
+// uint256[] public dkgReadysCount;
+func (s *GovernanceStateHelper) DKGMPKReadysCount(round *big.Int) *big.Int {
+ loc := new(big.Int).Add(s.getSlotLoc(big.NewInt(dkgReadysCountLoc)), round)
+ return s.getStateBigInt(loc)
+}
+func (s *GovernanceStateHelper) IncDKGMPKReadysCount(round *big.Int) {
+ loc := new(big.Int).Add(s.getSlotLoc(big.NewInt(dkgReadysCountLoc)), round)
+ count := s.getStateBigInt(loc)
+ s.setStateBigInt(loc, new(big.Int).Add(count, big.NewInt(1)))
+}
+
+// mapping(address => bool)[] public dkgFinalized;
+func (s *GovernanceStateHelper) DKGFinalized(round *big.Int, addr common.Address) bool {
+ baseLoc := new(big.Int).Add(s.getSlotLoc(big.NewInt(dkgFinalizedLoc)), round)
+ mapLoc := s.getMapLoc(baseLoc, addr.Bytes())
+ return s.getStateBigInt(mapLoc).Cmp(big.NewInt(0)) != 0
+}
+func (s *GovernanceStateHelper) PutDKGFinalized(round *big.Int, addr common.Address, finalized bool) {
+ baseLoc := new(big.Int).Add(s.getSlotLoc(big.NewInt(dkgFinalizedLoc)), round)
+ mapLoc := s.getMapLoc(baseLoc, addr.Bytes())
+ res := big.NewInt(0)
+ if finalized {
+ res = big.NewInt(1)
+ }
+ s.setStateBigInt(mapLoc, res)
+}
+
+// uint256[] public dkgFinalizedsCount;
+func (s *GovernanceStateHelper) DKGFinalizedsCount(round *big.Int) *big.Int {
+ loc := new(big.Int).Add(s.getSlotLoc(big.NewInt(dkgFinalizedsCountLoc)), round)
+ return s.getStateBigInt(loc)
+}
+func (s *GovernanceStateHelper) IncDKGFinalizedsCount(round *big.Int) {
+ loc := new(big.Int).Add(s.getSlotLoc(big.NewInt(dkgFinalizedsCountLoc)), round)
+ count := s.getStateBigInt(loc)
+ s.setStateBigInt(loc, new(big.Int).Add(count, big.NewInt(1)))
+}
+
+// address public owner;
+func (s *GovernanceStateHelper) Owner() common.Address {
+ val := s.getState(common.BigToHash(big.NewInt(ownerLoc)))
+ return common.BytesToAddress(val.Bytes())
+}
+func (s *GovernanceStateHelper) SetOwner(newOwner common.Address) {
+ s.setState(common.BigToHash(big.NewInt(ownerLoc)), newOwner.Hash())
+}
+
+// uint256 public minStake;
+func (s *GovernanceStateHelper) MinStake() *big.Int {
+ return s.getStateBigInt(big.NewInt(minStakeLoc))
+}
+
+// uint256 public lockupPeriod;
+func (s *GovernanceStateHelper) LockupPeriod() *big.Int {
+ return s.getStateBigInt(big.NewInt(lockupPeriodLoc))
+}
+
+// uint256 public miningVelocity;
+func (s *GovernanceStateHelper) MiningVelocity() *big.Int {
+ return s.getStateBigInt(big.NewInt(miningVelocityLoc))
+}
+func (s *GovernanceStateHelper) HalfMiningVelocity() {
+ s.setStateBigInt(big.NewInt(miningVelocityLoc),
+ new(big.Int).Div(s.MiningVelocity(), big.NewInt(2)))
+}
+
+// uint256 public nextHalvingSupply;
+func (s *GovernanceStateHelper) NextHalvingSupply() *big.Int {
+ return s.getStateBigInt(big.NewInt(nextHalvingSupplyLoc))
+}
+func (s *GovernanceStateHelper) IncNextHalvingSupply(amount *big.Int) {
+ s.setStateBigInt(big.NewInt(nextHalvingSupplyLoc),
+ new(big.Int).Add(s.NextHalvingSupply(), amount))
+}
+
+// uint256 public lastHalvedAmount;
+func (s *GovernanceStateHelper) LastHalvedAmount() *big.Int {
+ return s.getStateBigInt(big.NewInt(lastHalvedAmountLoc))
+}
+func (s *GovernanceStateHelper) HalfLastHalvedAmount() {
+ s.setStateBigInt(big.NewInt(lastHalvedAmountLoc),
+ new(big.Int).Div(s.LastHalvedAmount(), big.NewInt(2)))
+}
+
+func (s *GovernanceStateHelper) MiningHalved() {
+ s.HalfMiningVelocity()
+ s.HalfLastHalvedAmount()
+ s.IncNextHalvingSupply(s.LastHalvedAmount())
+}
+
+// uint256 public blockGasLimit;
+func (s *GovernanceStateHelper) BlockGasLimit() *big.Int {
+ return s.getStateBigInt(big.NewInt(blockGasLimitLoc))
+}
+func (s *GovernanceStateHelper) SetBlockGasLimit(reward *big.Int) {
+ s.setStateBigInt(big.NewInt(blockGasLimitLoc), reward)
+}
+
+// uint256 public numChains;
+func (s *GovernanceStateHelper) NumChains() *big.Int {
+ return s.getStateBigInt(big.NewInt(numChainsLoc))
+}
+
+// uint256 public lambdaBA;
+func (s *GovernanceStateHelper) LambdaBA() *big.Int {
+ return s.getStateBigInt(big.NewInt(lambdaBALoc))
+}
+
+// uint256 public lambdaDKG;
+func (s *GovernanceStateHelper) LambdaDKG() *big.Int {
+ return s.getStateBigInt(big.NewInt(lambdaDKGLoc))
+}
+
+// uint256 public k;
+func (s *GovernanceStateHelper) K() *big.Int {
+ return s.getStateBigInt(big.NewInt(kLoc))
+}
+
+// uint256 public phiRatio; // stored as PhiRatio * 10^6
+func (s *GovernanceStateHelper) PhiRatio() *big.Int {
+ return s.getStateBigInt(big.NewInt(phiRatioLoc))
+}
+
+// uint256 public notarySetSize;
+func (s *GovernanceStateHelper) NotarySetSize() *big.Int {
+ return s.getStateBigInt(big.NewInt(notarySetSizeLoc))
+}
+
+// uint256 public dkgSetSize;
+func (s *GovernanceStateHelper) DKGSetSize() *big.Int {
+ return s.getStateBigInt(big.NewInt(dkgSetSizeLoc))
+}
+
+// uint256 public roundInterval;
+func (s *GovernanceStateHelper) RoundInterval() *big.Int {
+ return s.getStateBigInt(big.NewInt(roundIntervalLoc))
+}
+
+// uint256 public minBlockInterval;
+func (s *GovernanceStateHelper) MinBlockInterval() *big.Int {
+ return s.getStateBigInt(big.NewInt(minBlockIntervalLoc))
+}
+
+// uint256[] public fineValues;
+func (s *GovernanceStateHelper) FineValue(index *big.Int) *big.Int {
+ arrayBaseLoc := s.getSlotLoc(big.NewInt(fineValuesLoc))
+ return s.getStateBigInt(new(big.Int).Add(arrayBaseLoc, index))
+}
+func (s *GovernanceStateHelper) FineValues() []*big.Int {
+ len := s.getStateBigInt(big.NewInt(fineValuesLoc))
+ result := make([]*big.Int, len.Uint64())
+ for i := 0; i < int(len.Uint64()); i++ {
+ result[i] = s.FineValue(big.NewInt(int64(i)))
+ }
+ return result
+}
+func (s *GovernanceStateHelper) SetFineValues(values []*big.Int) {
+ s.setStateBigInt(big.NewInt(fineValuesLoc), big.NewInt(int64(len(values))))
+
+ arrayBaseLoc := s.getSlotLoc(big.NewInt(fineValuesLoc))
+ for i, v := range values {
+ s.setStateBigInt(new(big.Int).Add(arrayBaseLoc, big.NewInt(int64(i))), v)
+ }
+}
+
+// uint256[] public fineRdecords;
+func (s *GovernanceStateHelper) FineRecords(recordHash Bytes32) bool {
+ loc := s.getMapLoc(big.NewInt(finedRecordsLoc), recordHash[:])
+ return s.getStateBigInt(loc).Cmp(big.NewInt(0)) > 0
+}
+func (s *GovernanceStateHelper) SetFineRecords(recordHash Bytes32, status bool) {
+ loc := s.getMapLoc(big.NewInt(finedRecordsLoc), recordHash[:])
+ value := int64(0)
+ if status {
+ value = int64(1)
+ }
+ s.setStateBigInt(loc, big.NewInt(value))
+}
+
+// Stake is a helper function for creating genesis state.
+func (s *GovernanceStateHelper) Stake(
+ addr common.Address, publicKey []byte, staked *big.Int,
+ name, email, location, url string) {
+ offset := s.LenNodes()
+ node := &nodeInfo{
+ Owner: addr,
+ PublicKey: publicKey,
+ Staked: staked,
+ Fined: big.NewInt(0),
+ Name: name,
+ Email: email,
+ Location: location,
+ Url: url,
+ }
+ s.PushNode(node)
+ if err := s.PutNodeOffsets(node, offset); err != nil {
+ panic(err)
+ }
+
+ if staked.Cmp(big.NewInt(0)) == 0 {
+ return
+ }
+
+ offset = s.LenDelegators(addr)
+ s.PushDelegator(addr, &delegatorInfo{
+ Owner: addr,
+ Value: staked,
+ UndelegatedAt: big.NewInt(0),
+ })
+ s.PutDelegatorOffset(addr, addr, offset)
+
+ // Add to network total staked.
+ s.IncTotalStaked(staked)
+}
+
+const decimalMultiplier = 100000000.0
+
+// Configuration returns the current configuration.
+func (s *GovernanceStateHelper) Configuration() *params.DexconConfig {
+ return &params.DexconConfig{
+ MinStake: s.getStateBigInt(big.NewInt(minStakeLoc)),
+ LockupPeriod: s.getStateBigInt(big.NewInt(lockupPeriodLoc)).Uint64(),
+ MiningVelocity: float32(s.getStateBigInt(big.NewInt(miningVelocityLoc)).Uint64()) / decimalMultiplier,
+ NextHalvingSupply: s.getStateBigInt(big.NewInt(nextHalvingSupplyLoc)),
+ LastHalvedAmount: s.getStateBigInt(big.NewInt(lastHalvedAmountLoc)),
+ BlockGasLimit: s.getStateBigInt(big.NewInt(blockGasLimitLoc)).Uint64(),
+ NumChains: uint32(s.getStateBigInt(big.NewInt(numChainsLoc)).Uint64()),
+ LambdaBA: s.getStateBigInt(big.NewInt(lambdaBALoc)).Uint64(),
+ LambdaDKG: s.getStateBigInt(big.NewInt(lambdaDKGLoc)).Uint64(),
+ K: uint32(s.getStateBigInt(big.NewInt(kLoc)).Uint64()),
+ PhiRatio: float32(s.getStateBigInt(big.NewInt(phiRatioLoc)).Uint64()) / decimalMultiplier,
+ NotarySetSize: uint32(s.getStateBigInt(big.NewInt(notarySetSizeLoc)).Uint64()),
+ DKGSetSize: uint32(s.getStateBigInt(big.NewInt(dkgSetSizeLoc)).Uint64()),
+ RoundInterval: s.getStateBigInt(big.NewInt(roundIntervalLoc)).Uint64(),
+ MinBlockInterval: s.getStateBigInt(big.NewInt(minBlockIntervalLoc)).Uint64(),
+ FineValues: s.FineValues(),
+ }
+}
+
+// UpdateConfiguration updates system configuration.
+func (s *GovernanceStateHelper) UpdateConfiguration(cfg *params.DexconConfig) {
+ s.setStateBigInt(big.NewInt(minStakeLoc), cfg.MinStake)
+ s.setStateBigInt(big.NewInt(lockupPeriodLoc), big.NewInt(int64(cfg.LockupPeriod)))
+ s.setStateBigInt(big.NewInt(miningVelocityLoc), big.NewInt(int64(cfg.MiningVelocity*decimalMultiplier)))
+ s.setStateBigInt(big.NewInt(nextHalvingSupplyLoc), cfg.NextHalvingSupply)
+ s.setStateBigInt(big.NewInt(lastHalvedAmountLoc), cfg.LastHalvedAmount)
+ s.setStateBigInt(big.NewInt(blockGasLimitLoc), big.NewInt(int64(cfg.BlockGasLimit)))
+ s.setStateBigInt(big.NewInt(numChainsLoc), big.NewInt(int64(cfg.NumChains)))
+ s.setStateBigInt(big.NewInt(lambdaBALoc), big.NewInt(int64(cfg.LambdaBA)))
+ s.setStateBigInt(big.NewInt(lambdaDKGLoc), big.NewInt(int64(cfg.LambdaDKG)))
+ s.setStateBigInt(big.NewInt(kLoc), big.NewInt(int64(cfg.K)))
+ s.setStateBigInt(big.NewInt(phiRatioLoc), big.NewInt(int64(cfg.PhiRatio*decimalMultiplier)))
+ s.setStateBigInt(big.NewInt(notarySetSizeLoc), big.NewInt(int64(cfg.NotarySetSize)))
+ s.setStateBigInt(big.NewInt(dkgSetSizeLoc), big.NewInt(int64(cfg.DKGSetSize)))
+ s.setStateBigInt(big.NewInt(roundIntervalLoc), big.NewInt(int64(cfg.RoundInterval)))
+ s.setStateBigInt(big.NewInt(minBlockIntervalLoc), big.NewInt(int64(cfg.MinBlockInterval)))
+ s.SetFineValues(cfg.FineValues)
+}
+
+type rawConfigStruct struct {
+ MinStake *big.Int
+ LockupPeriod *big.Int
+ MiningVelocity *big.Int
+ BlockGasLimit *big.Int
+ NumChains *big.Int
+ LambdaBA *big.Int
+ LambdaDKG *big.Int
+ K *big.Int
+ PhiRatio *big.Int
+ NotarySetSize *big.Int
+ DKGSetSize *big.Int
+ RoundInterval *big.Int
+ MinBlockInterval *big.Int
+ FineValues []*big.Int
+}
+
+// UpdateConfigurationRaw updates system configuration.
+func (s *GovernanceStateHelper) UpdateConfigurationRaw(cfg *rawConfigStruct) {
+ s.setStateBigInt(big.NewInt(minStakeLoc), cfg.MinStake)
+ s.setStateBigInt(big.NewInt(lockupPeriodLoc), cfg.LockupPeriod)
+ s.setStateBigInt(big.NewInt(miningVelocityLoc), cfg.MiningVelocity)
+ s.setStateBigInt(big.NewInt(blockGasLimitLoc), cfg.BlockGasLimit)
+ s.setStateBigInt(big.NewInt(numChainsLoc), cfg.NumChains)
+ s.setStateBigInt(big.NewInt(lambdaBALoc), cfg.LambdaBA)
+ s.setStateBigInt(big.NewInt(lambdaDKGLoc), cfg.LambdaDKG)
+ s.setStateBigInt(big.NewInt(kLoc), cfg.K)
+ s.setStateBigInt(big.NewInt(phiRatioLoc), cfg.PhiRatio)
+ s.setStateBigInt(big.NewInt(notarySetSizeLoc), cfg.NotarySetSize)
+ s.setStateBigInt(big.NewInt(dkgSetSizeLoc), cfg.DKGSetSize)
+ s.setStateBigInt(big.NewInt(roundIntervalLoc), cfg.RoundInterval)
+ s.setStateBigInt(big.NewInt(minBlockIntervalLoc), cfg.MinBlockInterval)
+ s.SetFineValues(cfg.FineValues)
+}
+
+// event ConfigurationChanged();
+func (s *GovernanceStateHelper) emitConfigurationChangedEvent() {
+ s.StateDB.AddLog(&types.Log{
+ Address: GovernanceContractAddress,
+ Topics: []common.Hash{events["ConfigurationChanged"].Id()},
+ Data: []byte{},
+ })
+}
+
+// event CRSProposed(uint256 round, bytes32 crs);
+func (s *GovernanceStateHelper) emitCRSProposed(round *big.Int, crs common.Hash) {
+ s.StateDB.AddLog(&types.Log{
+ Address: GovernanceContractAddress,
+ Topics: []common.Hash{events["CRSProposed"].Id(), common.BigToHash(round)},
+ Data: crs.Bytes(),
+ })
+}
+
+// event Staked(address indexed NodeAddress, uint256 Amount);
+func (s *GovernanceStateHelper) emitStaked(nodeAddr common.Address) {
+ s.StateDB.AddLog(&types.Log{
+ Address: GovernanceContractAddress,
+ Topics: []common.Hash{events["Staked"].Id(), nodeAddr.Hash()},
+ Data: []byte{},
+ })
+}
+
+// event Unstaked(address indexed NodeAddress);
+func (s *GovernanceStateHelper) emitUnstaked(nodeAddr common.Address) {
+ s.StateDB.AddLog(&types.Log{
+ Address: GovernanceContractAddress,
+ Topics: []common.Hash{events["Unstaked"].Id(), nodeAddr.Hash()},
+ Data: []byte{},
+ })
+}
+
+// event Delegated(address indexed NodeAddress, address indexed DelegatorAddress, uint256 Amount);
+func (s *GovernanceStateHelper) emitDelegated(nodeAddr, delegatorAddr common.Address, amount *big.Int) {
+ s.StateDB.AddLog(&types.Log{
+ Address: GovernanceContractAddress,
+ Topics: []common.Hash{events["Delegated"].Id(), nodeAddr.Hash(), delegatorAddr.Hash()},
+ Data: common.BigToHash(amount).Bytes(),
+ })
+}
+
+// event Undelegated(address indexed NodeAddress, address indexed DelegatorAddress);
+func (s *GovernanceStateHelper) emitUndelegated(nodeAddr, delegatorAddr common.Address) {
+ s.StateDB.AddLog(&types.Log{
+ Address: GovernanceContractAddress,
+ Topics: []common.Hash{events["Undelegated"].Id(), nodeAddr.Hash(), delegatorAddr.Hash()},
+ Data: []byte{},
+ })
+}
+
+// event Withdrawn(address indexed NodeAddress, uint256 Amount);
+func (s *GovernanceStateHelper) emitWithdrawn(nodeAddr common.Address, amount *big.Int) {
+ s.StateDB.AddLog(&types.Log{
+ Address: GovernanceContractAddress,
+ Topics: []common.Hash{events["Withdrawn"].Id(), nodeAddr.Hash()},
+ Data: common.BigToHash(amount).Bytes(),
+ })
+}
+
+// event ForkReported(address indexed NodeAddress, address indexed Type, bytes Arg1, bytes Arg2);
+func (s *GovernanceStateHelper) emitForkReported(nodeAddr common.Address, reportType *big.Int, arg1, arg2 []byte) {
+
+ t, err := abi.NewType("bytes")
+ if err != nil {
+ panic(err)
+ }
+
+ arg := abi.Arguments{
+ abi.Argument{
+ Name: "Arg1",
+ Type: t,
+ Indexed: false,
+ },
+ abi.Argument{
+ Name: "Arg2",
+ Type: t,
+ Indexed: false,
+ },
+ }
+
+ data, err := arg.Pack(arg1, arg2)
+ if err != nil {
+ panic(err)
+ }
+ s.StateDB.AddLog(&types.Log{
+ Address: GovernanceContractAddress,
+ Topics: []common.Hash{events["ForkReported"].Id(), nodeAddr.Hash()},
+ Data: data,
+ })
+}
+
+// event Fined(address indexed NodeAddress, uint256 Amount);
+func (s *GovernanceStateHelper) emitFined(nodeAddr common.Address, amount *big.Int) {
+ s.StateDB.AddLog(&types.Log{
+ Address: GovernanceContractAddress,
+ Topics: []common.Hash{events["Fined"].Id(), nodeAddr.Hash()},
+ Data: common.BigToHash(amount).Bytes(),
+ })
+}
+
+// event FinePaid(address indexed NodeAddress, uint256 Amount);
+func (s *GovernanceStateHelper) emitFinePaid(nodeAddr common.Address, amount *big.Int) {
+ s.StateDB.AddLog(&types.Log{
+ Address: GovernanceContractAddress,
+ Topics: []common.Hash{events["FinePaid"].Id(), nodeAddr.Hash()},
+ Data: common.BigToHash(amount).Bytes(),
+ })
+}
+
+// GovernanceContract represents the governance contract of DEXCON.
+type GovernanceContract struct {
+ evm *EVM
+ state GovernanceStateHelper
+ contract *Contract
+}
+
+func newGovernanceContract(evm *EVM, contract *Contract) *GovernanceContract {
+ return &GovernanceContract{
+ evm: evm,
+ state: GovernanceStateHelper{evm.StateDB},
+ contract: contract,
+ }
+}
+
+func (g *GovernanceContract) Address() common.Address {
+ return GovernanceContractAddress
+}
+
+func (g *GovernanceContract) transfer(from, to common.Address, amount *big.Int) bool {
+ // TODO(w): add this to debug trace so it shows up as internal transaction.
+ if g.evm.CanTransfer(g.evm.StateDB, from, amount) {
+ g.evm.Transfer(g.evm.StateDB, from, to, amount)
+ return true
+ }
+ return false
+}
+
+func (g *GovernanceContract) useGas(gas uint64) ([]byte, error) {
+ if !g.contract.UseGas(gas) {
+ return nil, vm.ErrOutOfGas
+ }
+ return nil, nil
+}
+
+func (g *GovernanceContract) penalize() ([]byte, error) {
+ g.useGas(g.contract.Gas)
+ return nil, errExecutionReverted
+}
+
+func (g *GovernanceContract) inDKGSet(round *big.Int, nodeID coreTypes.NodeID) bool {
+ target := coreTypes.NewDKGSetTarget(coreCommon.Hash(g.state.CurrentCRS()))
+ ns := coreTypes.NewNodeSet()
+
+ configRound := big.NewInt(0) // If round < core.ConfigRoundShift, use 0.
+ if round.Uint64() >= core.ConfigRoundShift {
+ configRound = new(big.Int).Sub(round, big.NewInt(int64(core.ConfigRoundShift)))
+ }
+
+ statedb, err := g.evm.StateAtNumber(g.state.RoundHeight(configRound).Uint64())
+ if err != nil {
+ panic(err)
+ }
+
+ state := GovernanceStateHelper{statedb}
+ for _, x := range state.QualifiedNodes() {
+ mpk, err := ecdsa.NewPublicKeyFromByteSlice(x.PublicKey)
+ if err != nil {
+ panic(err)
+ }
+ ns.Add(coreTypes.NewNodeID(mpk))
+ }
+
+ dkgSet := ns.GetSubSet(int(g.state.DKGSetSize().Uint64()), target)
+ _, ok := dkgSet[nodeID]
+ return ok
+}
+
+func (g *GovernanceContract) addDKGComplaint(round *big.Int, comp []byte) ([]byte, error) {
+ if round.Cmp(g.state.Round()) != 0 {
+ return g.penalize()
+ }
+
+ caller := g.contract.Caller()
+
+ // Finalized caller is not allowed to propose complaint.
+ if g.state.DKGFinalized(round, caller) {
+ return g.penalize()
+ }
+
+ // Calculate 2f
+ threshold := new(big.Int).Mul(
+ big.NewInt(2),
+ new(big.Int).Div(g.state.DKGSetSize(), big.NewInt(3)))
+
+ // If 2f + 1 of DKG set is finalized, one can not propose complaint anymore.
+ if g.state.DKGFinalizedsCount(round).Cmp(threshold) > 0 {
+ return nil, errExecutionReverted
+ }
+
+ var dkgComplaint dkgTypes.Complaint
+ if err := rlp.DecodeBytes(comp, &dkgComplaint); err != nil {
+ return g.penalize()
+ }
+
+ // DKGComplaint must belongs to someone in DKG set.
+ if !g.inDKGSet(round, dkgComplaint.ProposerID) {
+ return g.penalize()
+ }
+
+ verified, _ := coreUtils.VerifyDKGComplaintSignature(&dkgComplaint)
+ if !verified {
+ return g.penalize()
+ }
+
+ mpk, err := g.state.GetDKGMasterPublicKeyByProposerID(
+ round, dkgComplaint.PrivateShare.ProposerID)
+ if err != nil {
+ return g.penalize()
+ }
+
+ // Verify DKG complaint is correct.
+ ok, err := coreUtils.VerifyDKGComplaint(&dkgComplaint, mpk)
+ if !ok || err != nil {
+ return g.penalize()
+ }
+
+ // Fine the attacker.
+ need, err := coreUtils.NeedPenaltyDKGPrivateShare(&dkgComplaint, mpk)
+ if err != nil {
+ return g.penalize()
+ }
+ if need {
+ fineValue := g.state.FineValue(big.NewInt(ReportTypeInvalidDKG))
+ offset := g.state.NodesOffsetByID(Bytes32(dkgComplaint.PrivateShare.ProposerID.Hash))
+ node := g.state.Node(offset)
+ if err := g.fine(node.Owner, fineValue, comp, nil); err != nil {
+ return g.penalize()
+ }
+ }
+
+ g.state.PushDKGComplaint(round, comp)
+
+ // Set this to relatively high to prevent spamming
+ return g.useGas(5000000)
+}
+
+func (g *GovernanceContract) addDKGMasterPublicKey(round *big.Int, mpk []byte) ([]byte, error) {
+ // Can only add DKG master public key of current and next round.
+ if round.Cmp(new(big.Int).Add(g.state.Round(), big.NewInt(1))) > 0 {
+ return g.penalize()
+ }
+
+ caller := g.contract.Caller()
+ offset := g.state.NodesOffsetByAddress(caller)
+
+ // Can not add dkg mpk if not staked.
+ if offset.Cmp(big.NewInt(0)) < 0 {
+ return nil, errExecutionReverted
+ }
+
+ // MPKReady caller is not allowed to propose mpk.
+ if g.state.DKGMPKReady(round, caller) {
+ return g.penalize()
+ }
+
+ // Calculate 2f
+ threshold := new(big.Int).Mul(
+ big.NewInt(2),
+ new(big.Int).Div(g.state.DKGSetSize(), big.NewInt(3)))
+
+ // If 2f + 1 of DKG set is mpk ready, one can not propose mpk anymore.
+ if g.state.DKGMPKReadysCount(round).Cmp(threshold) > 0 {
+ return nil, errExecutionReverted
+ }
+
+ var dkgMasterPK dkgTypes.MasterPublicKey
+ if err := rlp.DecodeBytes(mpk, &dkgMasterPK); err != nil {
+ return g.penalize()
+ }
+
+ // DKGMasterPublicKey must belongs to someone in DKG set.
+ if !g.inDKGSet(round, dkgMasterPK.ProposerID) {
+ return g.penalize()
+ }
+
+ verified, _ := coreUtils.VerifyDKGMasterPublicKeySignature(&dkgMasterPK)
+ if !verified {
+ return g.penalize()
+ }
+
+ g.state.PushDKGMasterPublicKey(round, mpk)
+
+ return g.useGas(100000)
+}
+
+func (g *GovernanceContract) addDKGMPKReady(round *big.Int, ready []byte) ([]byte, error) {
+ if round.Cmp(g.state.Round()) != 0 {
+ return g.penalize()
+ }
+
+ caller := g.contract.Caller()
+
+ var dkgReady dkgTypes.MPKReady
+ if err := rlp.DecodeBytes(ready, &dkgReady); err != nil {
+ return g.penalize()
+ }
+
+ // DKGFInalize must belongs to someone in DKG set.
+ if !g.inDKGSet(round, dkgReady.ProposerID) {
+ return g.penalize()
+ }
+
+ verified, _ := coreUtils.VerifyDKGMPKReadySignature(&dkgReady)
+ if !verified {
+ return g.penalize()
+ }
+
+ if !g.state.DKGMPKReady(round, caller) {
+ g.state.PutDKGMPKReady(round, caller, true)
+ g.state.IncDKGMPKReadysCount(round)
+ }
+
+ return g.useGas(100000)
+}
+func (g *GovernanceContract) addDKGFinalize(round *big.Int, finalize []byte) ([]byte, error) {
+ if round.Cmp(g.state.Round()) != 0 {
+ return g.penalize()
+ }
+
+ caller := g.contract.Caller()
+
+ var dkgFinalize dkgTypes.Finalize
+ if err := rlp.DecodeBytes(finalize, &dkgFinalize); err != nil {
+ return g.penalize()
+ }
+
+ // DKGFInalize must belongs to someone in DKG set.
+ if !g.inDKGSet(round, dkgFinalize.ProposerID) {
+ return g.penalize()
+ }
+
+ verified, _ := coreUtils.VerifyDKGFinalizeSignature(&dkgFinalize)
+ if !verified {
+ return g.penalize()
+ }
+
+ if !g.state.DKGFinalized(round, caller) {
+ g.state.PutDKGFinalized(round, caller, true)
+ g.state.IncDKGFinalizedsCount(round)
+ }
+
+ return g.useGas(100000)
+}
+
+func (g *GovernanceContract) delegate(nodeAddr common.Address) ([]byte, error) {
+ offset := g.state.NodesOffsetByAddress(nodeAddr)
+ if offset.Cmp(big.NewInt(0)) < 0 {
+ return nil, errExecutionReverted
+ }
+
+ caller := g.contract.Caller()
+ value := g.contract.Value()
+
+ // Can not delegate if no fund was sent.
+ if value.Cmp(big.NewInt(0)) == 0 {
+ return nil, errExecutionReverted
+ }
+
+ // Can not delegate if already delegated.
+ delegatorOffset := g.state.DelegatorsOffset(nodeAddr, caller)
+ if delegatorOffset.Cmp(big.NewInt(0)) >= 0 {
+ return nil, errExecutionReverted
+ }
+
+ // Add to the total staked of node.
+ node := g.state.Node(offset)
+ node.Staked = new(big.Int).Add(node.Staked, g.contract.Value())
+ g.state.UpdateNode(offset, node)
+
+ // Add to network total staked.
+ g.state.IncTotalStaked(g.contract.Value())
+
+ // Push delegator record.
+ offset = g.state.LenDelegators(nodeAddr)
+ g.state.PushDelegator(nodeAddr, &delegatorInfo{
+ Owner: caller,
+ Value: value,
+ UndelegatedAt: big.NewInt(0),
+ })
+ g.state.PutDelegatorOffset(nodeAddr, caller, offset)
+ g.state.emitDelegated(nodeAddr, caller, value)
+
+ return g.useGas(200000)
+}
+
+func (g *GovernanceContract) updateConfiguration(cfg *rawConfigStruct) ([]byte, error) {
+ // Only owner can update configuration.
+ if g.contract.Caller() != g.state.Owner() {
+ return nil, errExecutionReverted
+ }
+
+ g.state.UpdateConfigurationRaw(cfg)
+ g.state.emitConfigurationChangedEvent()
+ return nil, nil
+}
+
+func (g *GovernanceContract) stake(
+ publicKey []byte, name, email, location, url string) ([]byte, error) {
+
+ // Reject invalid inputs.
+ if len(name) >= 32 || len(email) >= 32 || len(location) >= 32 || len(url) >= 128 {
+ return g.penalize()
+ }
+
+ caller := g.contract.Caller()
+ offset := g.state.NodesOffsetByAddress(caller)
+
+ // Can not stake if already staked.
+ if offset.Cmp(big.NewInt(0)) >= 0 {
+ return nil, errExecutionReverted
+ }
+
+ offset = g.state.LenNodes()
+ node := &nodeInfo{
+ Owner: caller,
+ PublicKey: publicKey,
+ Staked: big.NewInt(0),
+ Fined: big.NewInt(0),
+ Name: name,
+ Email: email,
+ Location: location,
+ Url: url,
+ }
+ g.state.PushNode(node)
+ if err := g.state.PutNodeOffsets(node, offset); err != nil {
+ return g.penalize()
+ }
+
+ // Delegate fund to itself.
+ if g.contract.Value().Cmp(big.NewInt(0)) > 0 {
+ if ret, err := g.delegate(caller); err != nil {
+ return ret, err
+ }
+ }
+
+ g.state.emitStaked(caller)
+ return g.useGas(100000)
+}
+
+func (g *GovernanceContract) undelegateHelper(nodeAddr, caller common.Address) ([]byte, error) {
+ nodeOffset := g.state.NodesOffsetByAddress(nodeAddr)
+ if nodeOffset.Cmp(big.NewInt(0)) < 0 {
+ return nil, errExecutionReverted
+ }
+
+ offset := g.state.DelegatorsOffset(nodeAddr, caller)
+ if offset.Cmp(big.NewInt(0)) < 0 {
+ return nil, errExecutionReverted
+ }
+
+ node := g.state.Node(nodeOffset)
+ if node.Fined.Cmp(big.NewInt(0)) > 0 {
+ return nil, errExecutionReverted
+ }
+
+ delegator := g.state.Delegator(nodeAddr, offset)
+
+ if delegator.UndelegatedAt.Cmp(big.NewInt(0)) != 0 {
+ return nil, errExecutionReverted
+ }
+
+ // Set undelegate time.
+ delegator.UndelegatedAt = g.evm.Time
+ g.state.UpdateDelegator(nodeAddr, offset, delegator)
+
+ // Subtract from the total staked of node.
+ node.Staked = new(big.Int).Sub(node.Staked, delegator.Value)
+ g.state.UpdateNode(nodeOffset, node)
+
+ // Subtract to network total staked.
+ g.state.DecTotalStaked(delegator.Value)
+
+ g.state.emitUndelegated(nodeAddr, caller)
+
+ return g.useGas(100000)
+}
+
+func (g *GovernanceContract) undelegate(nodeAddr common.Address) ([]byte, error) {
+ return g.undelegateHelper(nodeAddr, g.contract.Caller())
+}
+
+func (g *GovernanceContract) withdraw(nodeAddr common.Address) ([]byte, error) {
+ caller := g.contract.Caller()
+
+ nodeOffset := g.state.NodesOffsetByAddress(nodeAddr)
+ if nodeOffset.Cmp(big.NewInt(0)) < 0 {
+ return nil, errExecutionReverted
+ }
+
+ offset := g.state.DelegatorsOffset(nodeAddr, caller)
+ if offset.Cmp(big.NewInt(0)) < 0 {
+ return nil, errExecutionReverted
+ }
+
+ delegator := g.state.Delegator(nodeAddr, offset)
+
+ // Not yet undelegated.
+ if delegator.UndelegatedAt.Cmp(big.NewInt(0)) == 0 {
+ return g.penalize()
+ }
+
+ unlockTime := new(big.Int).Add(delegator.UndelegatedAt, g.state.LockupPeriod())
+ if g.evm.Time.Cmp(unlockTime) <= 0 {
+ return g.penalize()
+ }
+
+ length := g.state.LenDelegators(nodeAddr)
+ lastIndex := new(big.Int).Sub(length, big.NewInt(1))
+
+ // Delete the delegator.
+ if offset.Cmp(lastIndex) != 0 {
+ lastNode := g.state.Delegator(nodeAddr, lastIndex)
+ g.state.UpdateDelegator(nodeAddr, offset, lastNode)
+ g.state.PutDelegatorOffset(nodeAddr, lastNode.Owner, offset)
+ }
+ g.state.DeleteDelegatorsOffset(nodeAddr, caller)
+ g.state.PopLastDelegator(nodeAddr)
+
+ // Return the staked fund.
+ if !g.transfer(GovernanceContractAddress, delegator.Owner, delegator.Value) {
+ return nil, errExecutionReverted
+ }
+
+ g.state.emitWithdrawn(nodeAddr, delegator.Value)
+
+ // We are the last delegator to withdraw the fund, remove the node info.
+ if g.state.LenDelegators(nodeAddr).Cmp(big.NewInt(0)) == 0 {
+ length := g.state.LenNodes()
+ lastIndex := new(big.Int).Sub(length, big.NewInt(1))
+
+ // Delete the node.
+ if offset.Cmp(lastIndex) != 0 {
+ lastNode := g.state.Node(lastIndex)
+ g.state.UpdateNode(offset, lastNode)
+ if err := g.state.PutNodeOffsets(lastNode, offset); err != nil {
+ panic(err)
+ }
+ }
+ g.state.DeleteNodesOffsetByAddress(nodeAddr)
+ g.state.PopLastNode()
+ }
+
+ return g.useGas(100000)
+}
+
+func (g *GovernanceContract) unstake() ([]byte, error) {
+ caller := g.contract.Caller()
+ offset := g.state.NodesOffsetByAddress(caller)
+ if offset.Cmp(big.NewInt(0)) < 0 {
+ return nil, errExecutionReverted
+ }
+
+ node := g.state.Node(offset)
+ if node.Fined.Cmp(big.NewInt(0)) > 0 {
+ return nil, errExecutionReverted
+ }
+
+ // Undelegate all delegators.
+ lenDelegators := g.state.LenDelegators(caller)
+ i := new(big.Int).Sub(lenDelegators, big.NewInt(1))
+ for i.Cmp(big.NewInt(0)) >= 0 {
+ delegator := g.state.Delegator(caller, i)
+ if ret, err := g.undelegateHelper(caller, delegator.Owner); err != nil {
+ return ret, err
+ }
+ i = i.Sub(i, big.NewInt(1))
+ }
+
+ g.state.emitUnstaked(caller)
+
+ return g.useGas(100000)
+}
+
+func (g *GovernanceContract) payFine(nodeAddr common.Address) ([]byte, error) {
+ caller := g.contract.Caller()
+
+ nodeOffset := g.state.NodesOffsetByAddress(nodeAddr)
+ if nodeOffset.Cmp(big.NewInt(0)) < 0 {
+ return nil, errExecutionReverted
+ }
+
+ offset := g.state.DelegatorsOffset(nodeAddr, caller)
+ if offset.Cmp(big.NewInt(0)) < 0 {
+ return nil, errExecutionReverted
+ }
+
+ node := g.state.Node(nodeOffset)
+ if node.Fined.Cmp(big.NewInt(0)) <= 0 || node.Fined.Cmp(g.contract.Value()) < 0 {
+ return nil, errExecutionReverted
+ }
+
+ node.Fined = new(big.Int).Sub(node.Fined, g.contract.Value())
+ g.state.UpdateNode(nodeOffset, node)
+
+ // TODO: paid fine should be added to award pool.
+
+ g.state.emitFinePaid(nodeAddr, g.contract.Value())
+
+ return g.useGas(100000)
+}
+
+func (g *GovernanceContract) proposeCRS(nextRound *big.Int, signedCRS []byte) ([]byte, error) {
+ round := g.state.Round()
+
+ if nextRound.Cmp(round) <= 0 {
+ return nil, errExecutionReverted
+ }
+
+ prevCRS := g.state.CRS(round)
+
+ // Prepare DKGMasterPublicKeys.
+ dkgMasterPKs := g.state.UniqueDKGMasterPublicKeys(round)
+
+ // Prepare DKGComplaints.
+ var dkgComplaints []*dkgTypes.Complaint
+ for _, comp := range g.state.DKGComplaints(round) {
+ x := new(dkgTypes.Complaint)
+ if err := rlp.DecodeBytes(comp, x); err != nil {
+ panic(err)
+ }
+ dkgComplaints = append(dkgComplaints, x)
+ }
+
+ threshold := int(g.state.DKGSetSize().Uint64()/3 + 1)
+
+ dkgGPK, err := core.NewDKGGroupPublicKey(
+ round.Uint64(), dkgMasterPKs, dkgComplaints, threshold)
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ signature := coreCrypto.Signature{
+ Type: "bls",
+ Signature: signedCRS,
+ }
+ if !dkgGPK.VerifySignature(coreCommon.Hash(prevCRS), signature) {
+ return g.penalize()
+ }
+
+ // Save new CRS into state and increase round.
+ newCRS := crypto.Keccak256(signedCRS)
+ crs := common.BytesToHash(newCRS)
+
+ g.state.PushCRS(crs)
+ g.state.emitCRSProposed(nextRound, crs)
+
+ // To encourage DKG set to propose the correct value, correctly submitting
+ // this should cause nothing.
+ return g.useGas(0)
+}
+
+type sortBytes [][]byte
+
+func (s sortBytes) Less(i, j int) bool {
+ return bytes.Compare(s[i], s[j]) < 0
+}
+
+func (s sortBytes) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+func (s sortBytes) Len() int {
+ return len(s)
+}
+
+func (g *GovernanceContract) fine(nodeAddr common.Address, amount *big.Int, payloads ...[]byte) error {
+ sort.Sort(sortBytes(payloads))
+
+ hash := Bytes32(crypto.Keccak256Hash(payloads...))
+ if g.state.FineRecords(hash) {
+ return errors.New("already fined")
+ }
+ g.state.SetFineRecords(hash, true)
+
+ nodeOffset := g.state.NodesOffsetByAddress(nodeAddr)
+ if nodeOffset.Cmp(big.NewInt(0)) < 0 {
+ return errExecutionReverted
+ }
+
+ // Set fined value.
+ node := g.state.Node(nodeOffset)
+ node.Fined = new(big.Int).Add(node.Fined, amount)
+ g.state.UpdateNode(nodeOffset, node)
+
+ g.state.emitFined(nodeAddr, amount)
+
+ return nil
+}
+
+func (g *GovernanceContract) report(reportType *big.Int, arg1, arg2 []byte) ([]byte, error) {
+ typeEnum := ReportType(reportType.Uint64())
+ var reportedNodeID coreTypes.NodeID
+
+ switch typeEnum {
+ case ReportTypeForkVote:
+ vote1 := new(coreTypes.Vote)
+ if err := rlp.DecodeBytes(arg1, vote1); err != nil {
+ return g.penalize()
+ }
+ vote2 := new(coreTypes.Vote)
+ if err := rlp.DecodeBytes(arg2, vote2); err != nil {
+ return g.penalize()
+ }
+ need, err := coreUtils.NeedPenaltyForkVote(vote1, vote2)
+ if !need || err != nil {
+ return g.penalize()
+ }
+ reportedNodeID = vote1.ProposerID
+ case ReportTypeForkBlock:
+ block1 := new(coreTypes.Block)
+ if err := rlp.DecodeBytes(arg1, block1); err != nil {
+ return g.penalize()
+ }
+ block2 := new(coreTypes.Block)
+ if err := rlp.DecodeBytes(arg2, block2); err != nil {
+ return g.penalize()
+ }
+ need, err := coreUtils.NeedPenaltyForkBlock(block1, block2)
+ if !need || err != nil {
+ return g.penalize()
+ }
+ reportedNodeID = block1.ProposerID
+ default:
+ return g.penalize()
+ }
+
+ offset := g.state.NodesOffsetByID(Bytes32(reportedNodeID.Hash))
+ node := g.state.Node(offset)
+
+ g.state.emitForkReported(node.Owner, reportType, arg1, arg2)
+
+ fineValue := g.state.FineValue(reportType)
+ if err := g.fine(node.Owner, fineValue, arg1, arg2); err != nil {
+ return nil, errExecutionReverted
+ }
+ return nil, nil
+}
+
+func (g *GovernanceContract) transferOwnership(newOwner common.Address) ([]byte, error) {
+ // Only owner can update configuration.
+ if g.contract.Caller() != g.state.Owner() {
+ return nil, errExecutionReverted
+ }
+ g.state.SetOwner(newOwner)
+ return nil, nil
+}
+
+func (g *GovernanceContract) snapshotRound(round, height *big.Int) ([]byte, error) {
+ // Validate if this mapping is correct. Only block proposer need to verify this.
+ if g.evm.IsBlockProposer() {
+ realHeight, ok := g.evm.GetRoundHeight(round.Uint64())
+ if !ok {
+ return g.penalize()
+ }
+
+ if height.Cmp(new(big.Int).SetUint64(realHeight)) != 0 {
+ return g.penalize()
+ }
+ }
+
+ // Only allow updating the next round.
+ nextRound := g.state.LenRoundHeight()
+ if round.Cmp(nextRound) != 0 {
+ // No need to penalize, since the only possibility at this point is the
+ // round height is already snapshoted.
+ return nil, errExecutionReverted
+ }
+
+ g.state.PushRoundHeight(height)
+ return nil, nil
+}
diff --git a/core/vm/evm/governance_abi.go b/core/vm/evm/governance_abi.go
new file mode 100644
index 000000000..966c4c4f3
--- /dev/null
+++ b/core/vm/evm/governance_abi.go
@@ -0,0 +1,1133 @@
+// Copyright 2019 The dexon-consensus Authors
+// This file is part of the dexon-consensus library.
+//
+// The dexon-consensus library is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation, either version 3 of the License,
+// or (at your option) any later version.
+//
+// The dexon-consensus library is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the dexon-consensus library. If not, see
+// <http://www.gnu.org/licenses/>.
+
+package evm
+
+// The governance ABI is generated from:
+// https://github.com/dexon-foundation/governance-abi
+
+const GovernanceABIJSON = `
+[
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "address"
+ },
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "name": "delegatorsOffset",
+ "outputs": [
+ {
+ "name": "",
+ "type": "int256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ },
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "name": "dkgComplaints",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bytes"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "notarySetSize",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "dkgSetSize",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "totalSupply",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "name": "nodes",
+ "outputs": [
+ {
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "name": "publicKey",
+ "type": "bytes"
+ },
+ {
+ "name": "staked",
+ "type": "uint256"
+ },
+ {
+ "name": "fined",
+ "type": "uint256"
+ },
+ {
+ "name": "name",
+ "type": "string"
+ },
+ {
+ "name": "email",
+ "type": "string"
+ },
+ {
+ "name": "location",
+ "type": "string"
+ },
+ {
+ "name": "url",
+ "type": "string"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "miningVelocity",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "lambdaBA",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "minStake",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "name": "crs",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "phiRatio",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "name": "dkgMPKReadysCount",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ },
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "name": "dkgMPKReadys",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "address"
+ },
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "name": "delegators",
+ "outputs": [
+ {
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "name": "value",
+ "type": "uint256"
+ },
+ {
+ "name": "undelegated_at",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "blockGasLimit",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "name": "nodesOffsetByID",
+ "outputs": [
+ {
+ "name": "",
+ "type": "int256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "totalStaked",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "roundInterval",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "name": "nodesOffsetByAddress",
+ "outputs": [
+ {
+ "name": "",
+ "type": "int256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "nextHalvingSupply",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "owner",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "lastHalvedAmount",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "name": "finedRecords",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "lambdaDKG",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "name": "fineValues",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "name": "roundHeight",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "minBlockInterval",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "k",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ },
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "name": "dkgMasterPublicKeys",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bytes"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ },
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "name": "dkgFinalizeds",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "numChains",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "lockupPeriod",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "name": "dkgFinalizedsCount",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "anonymous": false,
+ "inputs": [],
+ "name": "ConfigurationChanged",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "Round",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "name": "CRS",
+ "type": "bytes32"
+ }
+ ],
+ "name": "CRSProposed",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "NodeAddress",
+ "type": "address"
+ }
+ ],
+ "name": "Staked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "NodeAddress",
+ "type": "address"
+ }
+ ],
+ "name": "Unstaked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "NodeAddress",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "DelegatorAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "Amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "Delegated",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "NodeAddress",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "DelegatorAddress",
+ "type": "address"
+ }
+ ],
+ "name": "Undelegated",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "NodeAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "Amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "Withdrawn",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "NodeAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "Type",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "name": "Arg1",
+ "type": "bytes"
+ },
+ {
+ "indexed": false,
+ "name": "Arg2",
+ "type": "bytes"
+ }
+ ],
+ "name": "ForkReported",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "NodeAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "Amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "Fined",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "NodeAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "Amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "FinePaid",
+ "type": "event"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "newOwner",
+ "type": "address"
+ }
+ ],
+ "name": "transferOwnership",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "MinStake",
+ "type": "uint256"
+ },
+ {
+ "name": "LockupPeriod",
+ "type": "uint256"
+ },
+ {
+ "name": "MiningVelocity",
+ "type": "uint256"
+ },
+ {
+ "name": "NextHalvingSupply",
+ "type": "uint256"
+ },
+ {
+ "name": "LastHalvingAmount",
+ "type": "uint256"
+ },
+ {
+ "name": "BlockGasLimit",
+ "type": "uint256"
+ },
+ {
+ "name": "NumChains",
+ "type": "uint256"
+ },
+ {
+ "name": "LambdaBA",
+ "type": "uint256"
+ },
+ {
+ "name": "LambdaDKG",
+ "type": "uint256"
+ },
+ {
+ "name": "K",
+ "type": "uint256"
+ },
+ {
+ "name": "PhiRatio",
+ "type": "uint256"
+ },
+ {
+ "name": "NotarySetSize",
+ "type": "uint256"
+ },
+ {
+ "name": "DKGSetSize",
+ "type": "uint256"
+ },
+ {
+ "name": "RoundInterval",
+ "type": "uint256"
+ },
+ {
+ "name": "MinBlockInterval",
+ "type": "uint256"
+ },
+ {
+ "name": "FineValues",
+ "type": "uint256[]"
+ }
+ ],
+ "name": "updateConfiguration",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "nodesLength",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "NodeAddress",
+ "type": "address"
+ }
+ ],
+ "name": "delegatorsLength",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "Round",
+ "type": "uint256"
+ },
+ {
+ "name": "Height",
+ "type": "uint256"
+ }
+ ],
+ "name": "snapshotRound",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "Round",
+ "type": "uint256"
+ },
+ {
+ "name": "SignedCRS",
+ "type": "bytes"
+ }
+ ],
+ "name": "proposeCRS",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "Round",
+ "type": "uint256"
+ },
+ {
+ "name": "Complaint",
+ "type": "bytes"
+ }
+ ],
+ "name": "addDKGComplaint",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "Round",
+ "type": "uint256"
+ },
+ {
+ "name": "PublicKey",
+ "type": "bytes"
+ }
+ ],
+ "name": "addDKGMasterPublicKey",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "Round",
+ "type": "uint256"
+ },
+ {
+ "name": "MPKReady",
+ "type": "bytes"
+ }
+ ],
+ "name": "addDKGMPKReady",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "Round",
+ "type": "uint256"
+ },
+ {
+ "name": "Finalize",
+ "type": "bytes"
+ }
+ ],
+ "name": "addDKGFinalize",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "PublicKey",
+ "type": "bytes"
+ },
+ {
+ "name": "Name",
+ "type": "string"
+ },
+ {
+ "name": "Email",
+ "type": "string"
+ },
+ {
+ "name": "Location",
+ "type": "string"
+ },
+ {
+ "name": "Url",
+ "type": "string"
+ }
+ ],
+ "name": "stake",
+ "outputs": [],
+ "payable": true,
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [],
+ "name": "unstake",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "NodeAddress",
+ "type": "address"
+ }
+ ],
+ "name": "delegate",
+ "outputs": [],
+ "payable": true,
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "NodeAddress",
+ "type": "address"
+ }
+ ],
+ "name": "undelegate",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "NodeAddress",
+ "type": "address"
+ }
+ ],
+ "name": "withdraw",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "NodeAddress",
+ "type": "address"
+ }
+ ],
+ "name": "payFine",
+ "outputs": [],
+ "payable": true,
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "Type",
+ "type": "uint256"
+ },
+ {
+ "name": "Arg1",
+ "type": "bytes"
+ },
+ {
+ "name": "Arg2",
+ "type": "bytes"
+ }
+ ],
+ "name": "report",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+]
+`
diff --git a/core/vm/evm/governance_test.go b/core/vm/evm/governance_test.go
new file mode 100644
index 000000000..1a67516ec
--- /dev/null
+++ b/core/vm/evm/governance_test.go
@@ -0,0 +1,1060 @@
+// Copyright 2018 The dexon-consensus Authors
+// This file is part of the dexon-consensus library.
+//
+// The dexon-consensus library is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation, either version 3 of the License,
+// or (at your option) any later version.
+//
+// The dexon-consensus library is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+// General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the dexon-consensus library. If not, see
+// <http://www.gnu.org/licenses/>.
+
+package evm
+
+import (
+ "bytes"
+ "crypto/ecdsa"
+ "math/big"
+ "math/rand"
+ "sort"
+ "testing"
+ "time"
+
+ coreCommon "github.com/dexon-foundation/dexon-consensus/common"
+ coreCrypto "github.com/dexon-foundation/dexon-consensus/core/crypto"
+ coreEcdsa "github.com/dexon-foundation/dexon-consensus/core/crypto/ecdsa"
+ coreTypes "github.com/dexon-foundation/dexon-consensus/core/types"
+ coreUtils "github.com/dexon-foundation/dexon-consensus/core/utils"
+
+ "github.com/dexon-foundation/dexon/common"
+ "github.com/dexon-foundation/dexon/core/state"
+ "github.com/dexon-foundation/dexon/crypto"
+ "github.com/dexon-foundation/dexon/ethdb"
+ "github.com/dexon-foundation/dexon/params"
+ "github.com/dexon-foundation/dexon/rlp"
+ "github.com/stretchr/testify/suite"
+)
+
+func init() {
+ rand.Seed(time.Now().UnixNano())
+}
+
+func randomBytes(minLength, maxLength int32) []byte {
+ length := rand.Int31()%(maxLength-minLength) + minLength
+ b := make([]byte, length)
+ for i := range b {
+ b[i] = byte(65 + rand.Int31()%60)
+ }
+ return b
+}
+
+type GovernanceStateHelperTestSuite struct {
+ suite.Suite
+
+ s *GovernanceStateHelper
+}
+
+func (g *GovernanceStateHelperTestSuite) SetupTest() {
+ db := state.NewDatabase(ethdb.NewMemDatabase())
+ statedb, err := state.New(common.Hash{}, db)
+ if err != nil {
+ panic(err)
+ }
+ g.s = &GovernanceStateHelper{statedb}
+}
+
+func (g *GovernanceStateHelperTestSuite) TestReadWriteBytes() {
+ for i := 0; i < 100; i++ {
+ // Short bytes.
+ loc := big.NewInt(rand.Int63())
+ data := randomBytes(3, 32)
+ g.s.writeBytes(loc, data)
+ read := g.s.readBytes(loc)
+ g.Require().Equal(0, bytes.Compare(data, read))
+
+ // long bytes.
+ loc = big.NewInt(rand.Int63())
+ data = randomBytes(33, 2560)
+ g.s.writeBytes(loc, data)
+ read = g.s.readBytes(loc)
+ g.Require().Equal(0, bytes.Compare(data, read))
+ }
+}
+
+func TestGovernanceStateHelper(t *testing.T) {
+ suite.Run(t, new(GovernanceStateHelperTestSuite))
+}
+
+type GovernanceContractTestSuite struct {
+ suite.Suite
+
+ config *params.DexconConfig
+ memDB *ethdb.MemDatabase
+ stateDB *state.StateDB
+ s *GovernanceStateHelper
+}
+
+func (g *GovernanceContractTestSuite) SetupTest() {
+ memDB := ethdb.NewMemDatabase()
+ stateDB, err := state.New(common.Hash{}, state.NewDatabase(memDB))
+ if err != nil {
+ panic(err)
+ }
+ g.memDB = memDB
+ g.stateDB = stateDB
+ g.s = &GovernanceStateHelper{stateDB}
+
+ config := params.TestnetChainConfig.Dexcon
+ config.LockupPeriod = 1000
+ config.NextHalvingSupply = new(big.Int).Mul(big.NewInt(1e18), big.NewInt(2.5e9))
+ config.LastHalvedAmount = new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1.5e9))
+ config.MiningVelocity = 0.1875
+
+ g.config = config
+
+ // Give governance contract balance so it will not be deleted because of being an empty state object.
+ stateDB.AddBalance(GovernanceContractAddress, big.NewInt(1))
+
+ // Genesis CRS.
+ crs := crypto.Keccak256Hash([]byte(config.GenesisCRSText))
+ g.s.PushCRS(crs)
+
+ // Round 0 height.
+ g.s.PushRoundHeight(big.NewInt(0))
+
+ // Owner.
+ g.s.SetOwner(g.config.Owner)
+
+ // Governance configuration.
+ g.s.UpdateConfiguration(config)
+
+ g.stateDB.Commit(true)
+}
+
+func (g *GovernanceContractTestSuite) newPrefundAccount() (*ecdsa.PrivateKey, common.Address) {
+ privKey, err := crypto.GenerateKey()
+ if err != nil {
+ panic(err)
+ }
+ address := crypto.PubkeyToAddress(privKey.PublicKey)
+
+ g.stateDB.AddBalance(address, new(big.Int).Mul(big.NewInt(1e18), big.NewInt(2e6)))
+ return privKey, address
+}
+
+func (g *GovernanceContractTestSuite) call(caller common.Address, input []byte, value *big.Int) ([]byte, error) {
+ context := Context{
+ CanTransfer: func(db StateDB, addr common.Address, amount *big.Int) bool {
+ return db.GetBalance(addr).Cmp(amount) >= 0
+ },
+ Transfer: func(db StateDB, sender common.Address, recipient common.Address, amount *big.Int) {
+ db.SubBalance(sender, amount)
+ db.AddBalance(recipient, amount)
+ },
+ GetRoundHeight: func(round uint64) (uint64, bool) {
+ switch round {
+ case 0:
+ return 0, true
+ case 1:
+ return 1000, true
+ case 2:
+ return 2000, true
+ }
+ return 0, false
+ },
+ Time: big.NewInt(time.Now().UnixNano() / 1000000),
+ BlockNumber: big.NewInt(0),
+ }
+
+ evm := NewEVM(context, g.stateDB, params.TestChainConfig, Config{IsBlockProposer: true})
+ ret, _, err := evm.Call(AccountRef(caller), GovernanceContractAddress, input, 10000000, value)
+ return ret, err
+}
+
+func (g *GovernanceContractTestSuite) TestTransferOwnership() {
+ _, addr := g.newPrefundAccount()
+
+ input, err := abiObject.Pack("transferOwnership", addr)
+ g.Require().NoError(err)
+
+ // Call with non-owner.
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NotNil(err)
+
+ // Call with owner.
+ _, err = g.call(g.config.Owner, input, big.NewInt(0))
+ g.Require().NoError(err)
+ g.Require().Equal(addr, g.s.Owner())
+}
+
+func (g *GovernanceContractTestSuite) TestStakeUnstakeWithoutExtraDelegators() {
+ privKey, addr := g.newPrefundAccount()
+ pk := crypto.FromECDSAPub(&privKey.PublicKey)
+
+ // Stake.
+ amount := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1e6))
+ balanceBeforeStake := g.stateDB.GetBalance(addr)
+ input, err := abiObject.Pack("stake", pk, "Test1", "test1@dexon.org", "Taipei, Taiwan", "https://dexon.org")
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, amount)
+ g.Require().NoError(err)
+
+ g.Require().Equal(1, int(g.s.LenNodes().Uint64()))
+ g.Require().Equal(1, len(g.s.QualifiedNodes()))
+ g.Require().Equal("Test1", g.s.Node(big.NewInt(0)).Name)
+ g.Require().Equal(amount.String(), g.s.TotalStaked().String())
+
+ // Check balance.
+ g.Require().Equal(new(big.Int).Sub(balanceBeforeStake, amount), g.stateDB.GetBalance(addr))
+ g.Require().Equal(new(big.Int).Add(big.NewInt(1), amount), g.stateDB.GetBalance(GovernanceContractAddress))
+
+ // Staking again should fail.
+ _, err = g.call(addr, input, amount)
+ g.Require().NotNil(err)
+
+ // Unstake.
+ input, err = abiObject.Pack("unstake")
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ g.Require().Equal(0, len(g.s.QualifiedNodes()))
+ g.Require().Equal(1, int(g.s.LenDelegators(addr).Uint64()))
+ g.Require().Equal(1, int(g.s.LenNodes().Uint64()))
+
+ node := g.s.Node(big.NewInt(0))
+ g.Require().Equal(big.NewInt(0).String(), node.Staked.String())
+ g.Require().Equal(big.NewInt(0).String(), g.s.TotalStaked().String())
+
+ // Wait for lockup time than withdraw.
+ time.Sleep(time.Second * 2)
+ input, err = abiObject.Pack("withdraw", addr)
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+
+ g.Require().Equal(0, len(g.s.QualifiedNodes()))
+ g.Require().Equal(0, int(g.s.LenDelegators(addr).Uint64()))
+ g.Require().Equal(0, int(g.s.LenNodes().Uint64()))
+
+ // Stake 2 nodes, and unstake the first then the second.
+
+ // 2nd node Stake.
+ privKey2, addr2 := g.newPrefundAccount()
+ pk2 := crypto.FromECDSAPub(&privKey2.PublicKey)
+ input, err = abiObject.Pack("stake", pk2, "Test2", "test2@dexon.org", "Taipei, Taiwan", "https://dexon.org")
+ g.Require().NoError(err)
+ _, err = g.call(addr2, input, amount)
+ g.Require().NoError(err)
+ g.Require().Equal("Test2", g.s.Node(big.NewInt(0)).Name)
+ g.Require().Equal(0, int(g.s.NodesOffsetByAddress(addr2).Int64()))
+
+ // 1st node Stake.
+ input, err = abiObject.Pack("stake", pk, "Test1", "test1@dexon.org", "Taipei, Taiwan", "https://dexon.org")
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, amount)
+ g.Require().NoError(err)
+
+ g.Require().Equal(2, len(g.s.QualifiedNodes()))
+ g.Require().Equal(new(big.Int).Mul(amount, big.NewInt(2)).String(), g.s.TotalStaked().String())
+
+ // 2nd node Unstake.
+ input, err = abiObject.Pack("unstake")
+ g.Require().NoError(err)
+ _, err = g.call(addr2, input, big.NewInt(0))
+ g.Require().NoError(err)
+ node = g.s.Node(big.NewInt(0))
+ g.Require().Equal("Test2", node.Name)
+ g.Require().Equal(big.NewInt(0).String(), node.Staked.String())
+ g.Require().Equal(1, len(g.s.QualifiedNodes()))
+ g.Require().Equal(amount.String(), g.s.TotalStaked().String())
+
+ time.Sleep(time.Second * 2)
+ input, err = abiObject.Pack("withdraw", addr2)
+ g.Require().NoError(err)
+ _, err = g.call(addr2, input, big.NewInt(0))
+ g.Require().NoError(err)
+ g.Require().Equal(1, len(g.s.QualifiedNodes()))
+
+ g.Require().Equal(1, int(g.s.LenNodes().Uint64()))
+ g.Require().Equal("Test1", g.s.Node(big.NewInt(0)).Name)
+ g.Require().Equal(-1, int(g.s.NodesOffsetByAddress(addr2).Int64()))
+
+ // 1st node Unstake.
+ input, err = abiObject.Pack("unstake")
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ g.Require().Equal(0, len(g.s.QualifiedNodes()))
+ g.Require().Equal(big.NewInt(0).String(), g.s.TotalStaked().String())
+
+ time.Sleep(time.Second * 2)
+ input, err = abiObject.Pack("withdraw", addr)
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+
+ g.Require().Equal(0, int(g.s.LenNodes().Uint64()))
+ g.Require().Equal(-1, int(g.s.NodesOffsetByAddress(addr).Int64()))
+ g.Require().Equal(-1, int(g.s.DelegatorsOffset(addr, addr).Int64()))
+
+ // Check balance.
+ g.Require().Equal(balanceBeforeStake, g.stateDB.GetBalance(addr))
+ g.Require().Equal(balanceBeforeStake, g.stateDB.GetBalance(addr2))
+ g.Require().Equal(big.NewInt(1), g.stateDB.GetBalance(GovernanceContractAddress))
+}
+
+func (g *GovernanceContractTestSuite) TestDelegateUndelegate() {
+ privKey, addr := g.newPrefundAccount()
+ pk := crypto.FromECDSAPub(&privKey.PublicKey)
+
+ // Stake.
+ input, err := abiObject.Pack("stake", pk, "Test1", "test1@dexon.org", "Taipei, Taiwan", "https://dexon.org")
+ g.Require().NoError(err)
+ ownerStaked := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(5e5))
+ _, err = g.call(addr, input, ownerStaked)
+ g.Require().NoError(err)
+ g.Require().Equal(0, len(g.s.QualifiedNodes()))
+ g.Require().Equal(addr, g.s.Delegator(addr, big.NewInt(0)).Owner)
+ g.Require().Equal(ownerStaked, g.s.Node(big.NewInt(0)).Staked)
+
+ // 1st delegator delegate to 1st node.
+ _, addrDelegator := g.newPrefundAccount()
+
+ balanceBeforeDelegate := g.stateDB.GetBalance(addrDelegator)
+ amount := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(3e5))
+ input, err = abiObject.Pack("delegate", addr)
+ g.Require().NoError(err)
+
+ _, err = g.call(addrDelegator, input, amount)
+ g.Require().NoError(err)
+ g.Require().Equal(new(big.Int).Sub(balanceBeforeDelegate, amount), g.stateDB.GetBalance(addrDelegator))
+ g.Require().Equal(addrDelegator, g.s.Delegator(addr, big.NewInt(1)).Owner)
+ g.Require().Equal(new(big.Int).Add(amount, ownerStaked), g.s.Node(big.NewInt(0)).Staked)
+ g.Require().Equal(g.s.Node(big.NewInt(0)).Staked.String(), g.s.TotalStaked().String())
+ g.Require().Equal(1, int(g.s.DelegatorsOffset(addr, addrDelegator).Int64()))
+
+ // Same person delegate the 2nd time should fail.
+ _, err = g.call(addrDelegator, input, big.NewInt(1e18))
+ g.Require().NotNil(err)
+
+ // Not yet qualified.
+ g.Require().Equal(0, len(g.s.QualifiedNodes()))
+
+ // 2nd delegator delegate to 1st node.
+ _, addrDelegator2 := g.newPrefundAccount()
+ _, err = g.call(addrDelegator2, input, amount)
+ g.Require().NoError(err)
+ g.Require().Equal(new(big.Int).Sub(balanceBeforeDelegate, amount), g.stateDB.GetBalance(addrDelegator2))
+ g.Require().Equal(addrDelegator2, g.s.Delegator(addr, big.NewInt(2)).Owner)
+ g.Require().Equal(new(big.Int).Add(ownerStaked, new(big.Int).Mul(amount, big.NewInt(2))),
+ g.s.Node(big.NewInt(0)).Staked)
+ g.Require().Equal(g.s.Node(big.NewInt(0)).Staked.String(), g.s.TotalStaked().String())
+ g.Require().Equal(2, int(g.s.DelegatorsOffset(addr, addrDelegator2).Int64()))
+
+ // Qualified.
+ g.Require().Equal(1, len(g.s.QualifiedNodes()))
+
+ // Undelegate addrDelegator.
+ balanceBeforeUnDelegate := g.stateDB.GetBalance(addrDelegator)
+ input, err = abiObject.Pack("undelegate", addr)
+ g.Require().NoError(err)
+ _, err = g.call(addrDelegator, input, big.NewInt(0))
+ g.Require().Equal(new(big.Int).Add(amount, ownerStaked), g.s.Node(big.NewInt(0)).Staked)
+ g.Require().Equal(g.s.Node(big.NewInt(0)).Staked.String(), g.s.TotalStaked().String())
+ g.Require().NoError(err)
+
+ // Undelegate the second time should fail.
+ _, err = g.call(addrDelegator, input, big.NewInt(0))
+ g.Require().Error(err)
+
+ // Withdraw within lockup time should fail.
+ input, err = abiObject.Pack("withdraw", addr)
+ g.Require().NoError(err)
+ _, err = g.call(addrDelegator, input, big.NewInt(0))
+ g.Require().NotNil(err)
+
+ g.Require().Equal(3, int(g.s.LenDelegators(addr).Uint64()))
+ g.Require().Equal(balanceBeforeUnDelegate, g.stateDB.GetBalance(addrDelegator))
+ g.Require().NotEqual(-1, int(g.s.DelegatorsOffset(addr, addrDelegator).Int64()))
+
+ // Wait for lockup time than withdraw.
+ time.Sleep(time.Second * 2)
+ input, err = abiObject.Pack("withdraw", addr)
+ g.Require().NoError(err)
+ _, err = g.call(addrDelegator, input, big.NewInt(0))
+ g.Require().NoError(err)
+
+ g.Require().Equal(2, int(g.s.LenDelegators(addr).Uint64()))
+ g.Require().Equal(new(big.Int).Add(balanceBeforeUnDelegate, amount), g.stateDB.GetBalance(addrDelegator))
+ g.Require().Equal(-1, int(g.s.DelegatorsOffset(addr, addrDelegator).Int64()))
+
+ // Withdraw when their is no delegation should fail.
+ time.Sleep(time.Second)
+ input, err = abiObject.Pack("withdraw", addr)
+ g.Require().NoError(err)
+ _, err = g.call(addrDelegator, input, big.NewInt(0))
+ g.Require().Error(err)
+
+ // Undelegate addrDelegator2.
+ balanceBeforeUnDelegate = g.stateDB.GetBalance(addrDelegator2)
+ input, err = abiObject.Pack("undelegate", addr)
+ g.Require().NoError(err)
+ _, err = g.call(addrDelegator2, input, big.NewInt(0))
+ g.Require().NoError(err)
+
+ g.Require().Equal(ownerStaked, g.s.Node(big.NewInt(0)).Staked)
+ g.Require().Equal(g.s.Node(big.NewInt(0)).Staked.String(), g.s.TotalStaked().String())
+
+ // Wait for lockup time than withdraw.
+ time.Sleep(time.Second * 2)
+ input, err = abiObject.Pack("withdraw", addr)
+ g.Require().NoError(err)
+ _, err = g.call(addrDelegator2, input, big.NewInt(0))
+ g.Require().NoError(err)
+
+ g.Require().Equal(1, int(g.s.LenDelegators(addr).Uint64()))
+ g.Require().Equal(new(big.Int).Add(balanceBeforeUnDelegate, amount), g.stateDB.GetBalance(addrDelegator2))
+ g.Require().Equal(-1, int(g.s.DelegatorsOffset(addr, addrDelegator2).Int64()))
+
+ // Unqualified
+ g.Require().Equal(0, len(g.s.QualifiedNodes()))
+
+ // Owner undelegate itself.
+ g.Require().Equal(1, int(g.s.LenNodes().Uint64()))
+ g.Require().Equal(1, int(g.s.LenDelegators(addr).Uint64()))
+
+ input, err = abiObject.Pack("undelegate", addr)
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ g.Require().Equal(big.NewInt(0).String(), g.s.Node(big.NewInt(0)).Staked.String())
+ g.Require().Equal(big.NewInt(0).String(), g.s.TotalStaked().String())
+
+ time.Sleep(time.Second * 2)
+ input, err = abiObject.Pack("withdraw", addr)
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+
+ g.Require().Equal(0, int(g.s.LenNodes().Uint64()))
+ g.Require().Equal(0, int(g.s.LenDelegators(addr).Uint64()))
+}
+
+func (g *GovernanceContractTestSuite) TestFine() {
+ privKey, addr := g.newPrefundAccount()
+ pk := crypto.FromECDSAPub(&privKey.PublicKey)
+
+ // Stake.
+ input, err := abiObject.Pack("stake", pk, "Test1", "test1@dexon.org", "Taipei, Taiwan", "https://dexon.org")
+ g.Require().NoError(err)
+ ownerStaked := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(5e5))
+ _, err = g.call(addr, input, ownerStaked)
+ g.Require().NoError(err)
+ g.Require().Equal(0, len(g.s.QualifiedNodes()))
+ g.Require().Equal(addr, g.s.Delegator(addr, big.NewInt(0)).Owner)
+ g.Require().Equal(ownerStaked, g.s.Node(big.NewInt(0)).Staked)
+
+ // 1st delegator delegate to 1st node.
+ _, addrDelegator := g.newPrefundAccount()
+
+ balanceBeforeDelegate := g.stateDB.GetBalance(addrDelegator)
+ amount := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(5e5))
+ input, err = abiObject.Pack("delegate", addr)
+ g.Require().NoError(err)
+
+ _, err = g.call(addrDelegator, input, amount)
+ g.Require().NoError(err)
+ g.Require().Equal(new(big.Int).Sub(balanceBeforeDelegate, amount), g.stateDB.GetBalance(addrDelegator))
+ g.Require().Equal(addrDelegator, g.s.Delegator(addr, big.NewInt(1)).Owner)
+ g.Require().Equal(new(big.Int).Add(amount, ownerStaked), g.s.Node(big.NewInt(0)).Staked)
+ g.Require().Equal(1, int(g.s.DelegatorsOffset(addr, addrDelegator).Int64()))
+
+ // Qualified.
+ g.Require().Equal(1, len(g.s.QualifiedNodes()))
+
+ // Paying to node without fine should fail.
+ input, err = abiObject.Pack("payFine", addr)
+ g.Require().NoError(err)
+ _, err = g.call(addrDelegator, input, amount)
+ g.Require().NotNil(err)
+
+ // Fined.
+ offset := g.s.NodesOffsetByAddress(addr)
+ g.Require().True(offset.Cmp(big.NewInt(0)) >= 0)
+ node := g.s.Node(offset)
+ node.Fined = new(big.Int).Set(amount)
+ g.s.UpdateNode(offset, node)
+ node = g.s.Node(offset)
+ g.Require().Equal(0, node.Fined.Cmp(amount))
+
+ // Not qualified after fined.
+ g.Require().Equal(0, len(g.s.QualifiedNodes()))
+
+ // Cannot undelegate before fines are paied.
+ input, err = abiObject.Pack("undelegate", addr)
+ g.Require().NoError(err)
+ _, err = g.call(addrDelegator, input, big.NewInt(0))
+ g.Require().NotNil(err)
+
+ // Only delegators can pay fine.
+ _, addrDelegator2 := g.newPrefundAccount()
+ input, err = abiObject.Pack("payFine", addr)
+ g.Require().NoError(err)
+ _, err = g.call(addrDelegator2, input, big.NewInt(5e5))
+ g.Require().NotNil(err)
+
+ // Paying more than fine should fail.
+ payAmount := new(big.Int).Add(amount, amount)
+ input, err = abiObject.Pack("payFine", addr)
+ g.Require().NoError(err)
+ _, err = g.call(addrDelegator, input, payAmount)
+ g.Require().NotNil(err)
+
+ // Pay the fine.
+ input, err = abiObject.Pack("payFine", addr)
+ g.Require().NoError(err)
+ _, err = g.call(addrDelegator, input, amount)
+ g.Require().NoError(err)
+
+ // Qualified.
+ g.Require().Equal(1, len(g.s.QualifiedNodes()))
+
+ // Can undelegate after all fines are paied.
+ input, err = abiObject.Pack("undelegate", addr)
+ g.Require().NoError(err)
+ _, err = g.call(addrDelegator, input, big.NewInt(0))
+ g.Require().NoError(err)
+}
+
+func (g *GovernanceContractTestSuite) TestUnstakeWithExtraDelegators() {
+ privKey, addr := g.newPrefundAccount()
+ pk := crypto.FromECDSAPub(&privKey.PublicKey)
+
+ // Stake.
+ amount := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(5e5))
+ input, err := abiObject.Pack("stake", pk, "Test1", "test1@dexon.org", "Taipei, Taiwan", "https://dexon.org")
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, amount)
+ g.Require().NoError(err)
+
+ // 1st delegator delegate to 1st node.
+ _, addrDelegator := g.newPrefundAccount()
+
+ balanceBeforeDelegate := g.stateDB.GetBalance(addrDelegator)
+ amount = new(big.Int).Mul(big.NewInt(1e18), big.NewInt(3e5))
+ input, err = abiObject.Pack("delegate", addr)
+ g.Require().NoError(err)
+
+ _, err = g.call(addrDelegator, input, amount)
+ g.Require().NoError(err)
+ g.Require().Equal(new(big.Int).Sub(balanceBeforeDelegate, amount), g.stateDB.GetBalance(addrDelegator))
+ g.Require().Equal(addrDelegator, g.s.Delegator(addr, big.NewInt(1)).Owner)
+ g.Require().Equal(0, len(g.s.QualifiedNodes()))
+
+ // 2st delegator delegate to 1st node.
+ _, addrDelegator2 := g.newPrefundAccount()
+
+ balanceBeforeDelegate = g.stateDB.GetBalance(addrDelegator2)
+ input, err = abiObject.Pack("delegate", addr)
+ g.Require().NoError(err)
+
+ _, err = g.call(addrDelegator2, input, amount)
+ g.Require().NoError(err)
+ g.Require().Equal(new(big.Int).Sub(balanceBeforeDelegate, amount), g.stateDB.GetBalance(addrDelegator2))
+ g.Require().Equal(addrDelegator2, g.s.Delegator(addr, big.NewInt(2)).Owner)
+
+ // Node is now qualified.
+ g.Require().Equal(1, len(g.s.QualifiedNodes()))
+
+ // Unstake.
+ input, err = abiObject.Pack("unstake")
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+
+ time.Sleep(time.Second * 2)
+ input, err = abiObject.Pack("withdraw", addr)
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ _, err = g.call(addrDelegator, input, big.NewInt(0))
+ g.Require().NoError(err)
+ _, err = g.call(addrDelegator2, input, big.NewInt(0))
+ g.Require().NoError(err)
+
+ g.Require().Equal(0, int(g.s.LenDelegators(addr).Uint64()))
+ g.Require().Equal(0, int(g.s.LenNodes().Uint64()))
+
+ // Check balance.
+ g.Require().Equal(balanceBeforeDelegate, g.stateDB.GetBalance(addr))
+ g.Require().Equal(balanceBeforeDelegate, g.stateDB.GetBalance(addrDelegator))
+ g.Require().Equal(balanceBeforeDelegate, g.stateDB.GetBalance(addrDelegator2))
+ g.Require().Equal(big.NewInt(1), g.stateDB.GetBalance(GovernanceContractAddress))
+}
+
+func (g *GovernanceContractTestSuite) TestUpdateConfiguration() {
+ _, addr := g.newPrefundAccount()
+
+ input, err := abiObject.Pack("updateConfiguration",
+ new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1e6)),
+ big.NewInt(1000),
+ big.NewInt(0.1875*decimalMultiplier),
+ big.NewInt(1e18),
+ big.NewInt(1e18),
+ big.NewInt(8000000),
+ big.NewInt(6),
+ big.NewInt(250),
+ big.NewInt(2500),
+ big.NewInt(0),
+ big.NewInt(667000),
+ big.NewInt(4),
+ big.NewInt(4),
+ big.NewInt(600000),
+ big.NewInt(900),
+ []*big.Int{big.NewInt(1), big.NewInt(1), big.NewInt(1)})
+ g.Require().NoError(err)
+
+ // Call with non-owner.
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NotNil(err)
+
+ // Call with owner.
+ _, err = g.call(g.config.Owner, input, big.NewInt(0))
+ g.Require().NoError(err)
+}
+
+func (g *GovernanceContractTestSuite) TestSnapshotRound() {
+ _, addr := g.newPrefundAccount()
+
+ // Wrong height.
+ input, err := abiObject.Pack("snapshotRound", big.NewInt(1), big.NewInt(666))
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NotNil(err)
+
+ // Invalid round.
+ input, err = abiObject.Pack("snapshotRound", big.NewInt(2), big.NewInt(2000))
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NotNil(err)
+
+ // Correct.
+ input, err = abiObject.Pack("snapshotRound", big.NewInt(1), big.NewInt(1000))
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+
+ // Duplicate round.
+ input, err = abiObject.Pack("snapshotRound", big.NewInt(1), big.NewInt(1000))
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NotNil(err)
+
+ // Invalid round.
+ input, err = abiObject.Pack("snapshotRound", big.NewInt(3), big.NewInt(3000))
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NotNil(err)
+
+ // Correct.
+ input, err = abiObject.Pack("snapshotRound", big.NewInt(2), big.NewInt(2000))
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+}
+
+func (g *GovernanceContractTestSuite) TestConfigurationReading() {
+ _, addr := g.newPrefundAccount()
+
+ // CRS.
+ input, err := abiObject.Pack("crs", big.NewInt(0))
+ g.Require().NoError(err)
+ res, err := g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ var crs0 [32]byte
+ err = abiObject.Unpack(&crs0, "crs", res)
+ g.Require().NoError(err)
+ g.Require().Equal(crypto.Keccak256Hash([]byte(g.config.GenesisCRSText)), common.BytesToHash(crs0[:]))
+
+ // Owner.
+ input, err = abiObject.Pack("owner")
+ g.Require().NoError(err)
+ res, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ var owner common.Address
+ err = abiObject.Unpack(&owner, "owner", res)
+ g.Require().NoError(err)
+ g.Require().Equal(g.config.Owner, owner)
+
+ // MinStake.
+ input, err = abiObject.Pack("minStake")
+ g.Require().NoError(err)
+ res, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ var value *big.Int
+ err = abiObject.Unpack(&value, "minStake", res)
+ g.Require().NoError(err)
+ g.Require().Equal(g.config.MinStake.String(), value.String())
+
+ // BlockReward.
+ input, err = abiObject.Pack("miningVelocity")
+ g.Require().NoError(err)
+ res, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ err = abiObject.Unpack(&value, "miningVelocity", res)
+ g.Require().NoError(err)
+ g.Require().Equal(g.config.MiningVelocity, float32(value.Uint64())/decimalMultiplier)
+
+ // BlockGasLimit.
+ input, err = abiObject.Pack("blockGasLimit")
+ g.Require().NoError(err)
+ res, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ err = abiObject.Unpack(&value, "blockGasLimit", res)
+ g.Require().NoError(err)
+ g.Require().Equal(g.config.BlockGasLimit, value.Uint64())
+
+ // NumChains.
+ input, err = abiObject.Pack("numChains")
+ g.Require().NoError(err)
+ res, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ err = abiObject.Unpack(&value, "numChains", res)
+ g.Require().NoError(err)
+ g.Require().Equal(g.config.NumChains, uint32(value.Uint64()))
+
+ // LambdaBA.
+ input, err = abiObject.Pack("lambdaBA")
+ g.Require().NoError(err)
+ res, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ err = abiObject.Unpack(&value, "lambdaBA", res)
+ g.Require().NoError(err)
+ g.Require().Equal(g.config.LambdaBA, value.Uint64())
+
+ // LambdaDKG.
+ input, err = abiObject.Pack("lambdaDKG")
+ g.Require().NoError(err)
+ res, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ err = abiObject.Unpack(&value, "lambdaDKG", res)
+ g.Require().NoError(err)
+ g.Require().Equal(g.config.LambdaDKG, value.Uint64())
+
+ // K.
+ input, err = abiObject.Pack("k")
+ g.Require().NoError(err)
+ res, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ err = abiObject.Unpack(&value, "k", res)
+ g.Require().NoError(err)
+ g.Require().Equal(g.config.K, uint32(value.Uint64()))
+
+ // PhiRatio.
+ input, err = abiObject.Pack("phiRatio")
+ g.Require().NoError(err)
+ res, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ err = abiObject.Unpack(&value, "phiRatio", res)
+ g.Require().NoError(err)
+ g.Require().Equal(g.config.PhiRatio, float32(value.Uint64())/decimalMultiplier)
+
+ // NotarySetSize.
+ input, err = abiObject.Pack("notarySetSize")
+ g.Require().NoError(err)
+ res, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ err = abiObject.Unpack(&value, "notarySetSize", res)
+ g.Require().NoError(err)
+ g.Require().Equal(g.config.NotarySetSize, uint32(value.Uint64()))
+
+ // DKGSetSize.
+ input, err = abiObject.Pack("dkgSetSize")
+ g.Require().NoError(err)
+ res, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ err = abiObject.Unpack(&value, "dkgSetSize", res)
+ g.Require().NoError(err)
+ g.Require().Equal(g.config.DKGSetSize, uint32(value.Uint64()))
+
+ // RoundInterval.
+ input, err = abiObject.Pack("roundInterval")
+ g.Require().NoError(err)
+ res, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ err = abiObject.Unpack(&value, "roundInterval", res)
+ g.Require().NoError(err)
+ g.Require().Equal(g.config.RoundInterval, value.Uint64())
+
+ // MinBlockInterval.
+ input, err = abiObject.Pack("minBlockInterval")
+ g.Require().NoError(err)
+ res, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ err = abiObject.Unpack(&value, "minBlockInterval", res)
+ g.Require().NoError(err)
+ g.Require().Equal(g.config.MinBlockInterval, value.Uint64())
+}
+
+func (g *GovernanceContractTestSuite) TestReportForkVote() {
+ key, addr := g.newPrefundAccount()
+ pkBytes := crypto.FromECDSAPub(&key.PublicKey)
+
+ // Stake.
+ amount := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(5e5))
+ input, err := abiObject.Pack("stake", pkBytes, "Test1", "test1@dexon.org", "Taipei, Taiwan", "https://dexon.org")
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, amount)
+ g.Require().NoError(err)
+
+ pubKey := coreEcdsa.NewPublicKeyFromECDSA(&key.PublicKey)
+ privKey := coreEcdsa.NewPrivateKeyFromECDSA(key)
+ vote1 := coreTypes.NewVote(coreTypes.VoteCom, coreCommon.NewRandomHash(), uint64(0))
+ vote1.ProposerID = coreTypes.NewNodeID(pubKey)
+
+ vote2 := vote1.Clone()
+ for vote2.BlockHash == vote1.BlockHash {
+ vote2.BlockHash = coreCommon.NewRandomHash()
+ }
+ vote1.Signature, err = privKey.Sign(coreUtils.HashVote(vote1))
+ g.Require().NoError(err)
+ vote2.Signature, err = privKey.Sign(coreUtils.HashVote(vote2))
+ g.Require().NoError(err)
+
+ vote1Bytes, err := rlp.EncodeToBytes(vote1)
+ g.Require().NoError(err)
+ vote2Bytes, err := rlp.EncodeToBytes(vote2)
+ g.Require().NoError(err)
+
+ // Report wrong type (fork block)
+ input, err = abiObject.Pack("report", big.NewInt(2), vote1Bytes, vote2Bytes)
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().Error(err)
+
+ input, err = abiObject.Pack("report", big.NewInt(1), vote1Bytes, vote2Bytes)
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+
+ node := g.s.Node(big.NewInt(0))
+ g.Require().Equal(node.Fined, g.s.FineValue(big.NewInt(1)))
+
+ // Duplicate report should fail.
+ input, err = abiObject.Pack("report", big.NewInt(1), vote1Bytes, vote2Bytes)
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().Error(err)
+
+ // Check if finedRecords is set.
+ payloads := [][]byte{vote1Bytes, vote2Bytes}
+ sort.Sort(sortBytes(payloads))
+
+ hash := Bytes32(crypto.Keccak256Hash(payloads...))
+ input, err = abiObject.Pack("finedRecords", hash)
+ g.Require().NoError(err)
+ res, err := g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+
+ var value bool
+ err = abiObject.Unpack(&value, "finedRecords", res)
+ g.Require().NoError(err)
+ g.Require().True(value)
+}
+
+func (g *GovernanceContractTestSuite) TestReportForkBlock() {
+ key, addr := g.newPrefundAccount()
+ pkBytes := crypto.FromECDSAPub(&key.PublicKey)
+
+ // Stake.
+ amount := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(5e5))
+ input, err := abiObject.Pack("stake", pkBytes, "Test1", "test1@dexon.org", "Taipei, Taiwan", "https://dexon.org")
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, amount)
+ g.Require().NoError(err)
+
+ privKey := coreEcdsa.NewPrivateKeyFromECDSA(key)
+ block1 := &coreTypes.Block{
+ ProposerID: coreTypes.NewNodeID(privKey.PublicKey()),
+ ParentHash: coreCommon.NewRandomHash(),
+ Timestamp: time.Now(),
+ }
+
+ block2 := block1.Clone()
+ for block2.ParentHash == block1.ParentHash {
+ block2.ParentHash = coreCommon.NewRandomHash()
+ }
+
+ hashBlock := func(block *coreTypes.Block) coreCommon.Hash {
+ block.PayloadHash = coreCrypto.Keccak256Hash(block.Payload)
+ var err error
+ block.Hash, err = coreUtils.HashBlock(block)
+ g.Require().NoError(err)
+ return block.Hash
+ }
+
+ block1.Signature, err = privKey.Sign(hashBlock(block1))
+ g.Require().NoError(err)
+ block2.Signature, err = privKey.Sign(hashBlock(block2))
+ g.Require().NoError(err)
+
+ block1Bytes, err := rlp.EncodeToBytes(block1)
+ g.Require().NoError(err)
+ block2Bytes, err := rlp.EncodeToBytes(block2)
+ g.Require().NoError(err)
+
+ // Report wrong type (fork vote)
+ input, err = abiObject.Pack("report", big.NewInt(1), block1Bytes, block2Bytes)
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().Error(err)
+
+ input, err = abiObject.Pack("report", big.NewInt(2), block1Bytes, block2Bytes)
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+
+ node := g.s.Node(big.NewInt(0))
+ g.Require().Equal(node.Fined, g.s.FineValue(big.NewInt(2)))
+
+ // Duplicate report should fail.
+ input, err = abiObject.Pack("report", big.NewInt(2), block1Bytes, block2Bytes)
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().Error(err)
+
+ // Check if finedRecords is set.
+ payloads := [][]byte{block1Bytes, block2Bytes}
+ sort.Sort(sortBytes(payloads))
+
+ hash := Bytes32(crypto.Keccak256Hash(payloads...))
+ input, err = abiObject.Pack("finedRecords", hash)
+ g.Require().NoError(err)
+ res, err := g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+
+ var value bool
+ err = abiObject.Unpack(&value, "finedRecords", res)
+ g.Require().NoError(err)
+ g.Require().True(value)
+}
+
+func (g *GovernanceContractTestSuite) TestMiscVariableReading() {
+ privKey, addr := g.newPrefundAccount()
+ pk := crypto.FromECDSAPub(&privKey.PublicKey)
+
+ input, err := abiObject.Pack("totalSupply")
+ g.Require().NoError(err)
+ res, err := g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+
+ input, err = abiObject.Pack("totalStaked")
+ g.Require().NoError(err)
+ res, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+
+ // Stake.
+ amount := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(5e5))
+ input, err = abiObject.Pack("stake", pk, "Test1", "test1@dexon.org", "Taipei, Taiwan", "https://dexon.org")
+ g.Require().NoError(err)
+ _, err = g.call(addr, input, amount)
+ g.Require().NoError(err)
+
+ // 1st delegator delegate to 1st node.
+ _, addrDelegator := g.newPrefundAccount()
+ amount = new(big.Int).Mul(big.NewInt(1e18), big.NewInt(3e5))
+ input, err = abiObject.Pack("delegate", addr)
+ g.Require().NoError(err)
+ _, err = g.call(addrDelegator, input, amount)
+ g.Require().NoError(err)
+
+ // 2st delegator delegate to 1st node.
+ _, addrDelegator2 := g.newPrefundAccount()
+ input, err = abiObject.Pack("delegate", addr)
+ g.Require().NoError(err)
+ _, err = g.call(addrDelegator2, input, amount)
+ g.Require().NoError(err)
+
+ input, err = abiObject.Pack("nodes", big.NewInt(0))
+ g.Require().NoError(err)
+ res, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+
+ input, err = abiObject.Pack("nodesLength")
+ g.Require().NoError(err)
+ res, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ var value *big.Int
+ err = abiObject.Unpack(&value, "nodesLength", res)
+ g.Require().NoError(err)
+ g.Require().Equal(1, int(value.Uint64()))
+
+ input, err = abiObject.Pack("nodesOffsetByAddress", addr)
+ g.Require().NoError(err)
+ res, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ err = abiObject.Unpack(&value, "nodesOffsetByAddress", res)
+ g.Require().NoError(err)
+ g.Require().Equal(0, int(value.Uint64()))
+
+ id, err := publicKeyToNodeID(pk)
+ g.Require().NoError(err)
+ input, err = abiObject.Pack("nodesOffsetByID", id)
+ g.Require().NoError(err)
+ res, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ err = abiObject.Unpack(&value, "nodesOffsetByID", res)
+ g.Require().NoError(err)
+ g.Require().Equal(0, int(value.Uint64()))
+
+ input, err = abiObject.Pack("delegators", addr, big.NewInt(0))
+ g.Require().NoError(err)
+ res, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+
+ input, err = abiObject.Pack("delegatorsLength", addr)
+ g.Require().NoError(err)
+ res, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ err = abiObject.Unpack(&value, "delegatorsLength", res)
+ g.Require().NoError(err)
+ g.Require().Equal(3, int(value.Uint64()))
+
+ input, err = abiObject.Pack("delegatorsOffset", addr, addrDelegator2)
+ g.Require().NoError(err)
+ res, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ err = abiObject.Unpack(&value, "delegatorsOffset", res)
+ g.Require().NoError(err)
+ g.Require().Equal(2, int(value.Uint64()))
+
+ input, err = abiObject.Pack("fineValues", big.NewInt(0))
+ g.Require().NoError(err)
+ res, err = g.call(addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+}
+
+func (g *GovernanceContractTestSuite) TestHalvingCondition() {
+ // TotalSupply 2.5B reached
+ g.s.MiningHalved()
+ g.Require().Equal(new(big.Int).Mul(big.NewInt(1e18), big.NewInt(3.25e9)).String(),
+ g.s.NextHalvingSupply().String())
+ g.Require().Equal(new(big.Int).Mul(big.NewInt(1e18), big.NewInt(0.75e9)).String(),
+ g.s.LastHalvedAmount().String())
+
+ // TotalSupply 3.25B reached
+ g.s.MiningHalved()
+ g.Require().Equal(new(big.Int).Mul(big.NewInt(1e18), big.NewInt(3.625e9)).String(),
+ g.s.NextHalvingSupply().String())
+ g.Require().Equal(new(big.Int).Mul(big.NewInt(1e18), big.NewInt(0.375e9)).String(),
+ g.s.LastHalvedAmount().String())
+}
+
+func TestGovernanceContract(t *testing.T) {
+ suite.Run(t, new(GovernanceContractTestSuite))
+}
diff --git a/core/vm/instructions.go b/core/vm/evm/instructions.go
index cb1f1bbaa..d37ab5e43 100644
--- a/core/vm/instructions.go
+++ b/core/vm/evm/instructions.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package vm
+package evm
import (
"encoding/binary"
@@ -25,6 +25,7 @@ import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/common/math"
"github.com/dexon-foundation/dexon/core/types"
+ "github.com/dexon-foundation/dexon/core/vm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/params"
"golang.org/x/crypto/sha3"
@@ -50,48 +51,48 @@ func init() {
}
}
-func opAdd(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.peek()
+func opAdd(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ x, y := stack.Pop(), stack.Peek()
math.U256(y.Add(x, y))
- interpreter.intPool.put(x)
+ interpreter.intPool.Put(x)
return nil, nil
}
-func opSub(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.peek()
+func opSub(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ x, y := stack.Pop(), stack.Peek()
math.U256(y.Sub(x, y))
- interpreter.intPool.put(x)
+ interpreter.intPool.Put(x)
return nil, nil
}
-func opMul(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.pop()
- stack.push(math.U256(x.Mul(x, y)))
+func opMul(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ x, y := stack.Pop(), stack.Pop()
+ stack.Push(math.U256(x.Mul(x, y)))
- interpreter.intPool.put(y)
+ interpreter.intPool.Put(y)
return nil, nil
}
-func opDiv(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.peek()
+func opDiv(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ x, y := stack.Pop(), stack.Peek()
if y.Sign() != 0 {
math.U256(y.Div(x, y))
} else {
y.SetUint64(0)
}
- interpreter.intPool.put(x)
+ interpreter.intPool.Put(x)
return nil, nil
}
-func opSdiv(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := math.S256(stack.pop()), math.S256(stack.pop())
- res := interpreter.intPool.getZero()
+func opSdiv(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ x, y := math.S256(stack.Pop()), math.S256(stack.Pop())
+ res := interpreter.intPool.GetZero()
if y.Sign() == 0 || x.Sign() == 0 {
- stack.push(res)
+ stack.Push(res)
} else {
if x.Sign() != y.Sign() {
res.Div(x.Abs(x), y.Abs(y))
@@ -99,29 +100,29 @@ func opSdiv(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
} else {
res.Div(x.Abs(x), y.Abs(y))
}
- stack.push(math.U256(res))
+ stack.Push(math.U256(res))
}
- interpreter.intPool.put(x, y)
+ interpreter.intPool.Put(x, y)
return nil, nil
}
-func opMod(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.pop()
+func opMod(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ x, y := stack.Pop(), stack.Pop()
if y.Sign() == 0 {
- stack.push(x.SetUint64(0))
+ stack.Push(x.SetUint64(0))
} else {
- stack.push(math.U256(x.Mod(x, y)))
+ stack.Push(math.U256(x.Mod(x, y)))
}
- interpreter.intPool.put(y)
+ interpreter.intPool.Put(y)
return nil, nil
}
-func opSmod(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := math.S256(stack.pop()), math.S256(stack.pop())
- res := interpreter.intPool.getZero()
+func opSmod(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ x, y := math.S256(stack.Pop()), math.S256(stack.Pop())
+ res := interpreter.intPool.GetZero()
if y.Sign() == 0 {
- stack.push(res)
+ stack.Push(res)
} else {
if x.Sign() < 0 {
res.Mod(x.Abs(x), y.Abs(y))
@@ -129,31 +130,31 @@ func opSmod(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
} else {
res.Mod(x.Abs(x), y.Abs(y))
}
- stack.push(math.U256(res))
+ stack.Push(math.U256(res))
}
- interpreter.intPool.put(x, y)
+ interpreter.intPool.Put(x, y)
return nil, nil
}
-func opExp(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- base, exponent := stack.pop(), stack.pop()
+func opExp(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ base, exponent := stack.Pop(), stack.Pop()
if base.Cmp(big2) == 0 && exponent.Cmp(big256) == -1 {
exp := exponent.Int64()
- stack.push(interpreter.intPool.get().Set(power2[exp]))
+ stack.Push(interpreter.intPool.Get().Set(power2[exp]))
} else {
- stack.push(math.Exp(base, exponent))
+ stack.Push(math.Exp(base, exponent))
}
- interpreter.intPool.put(base, exponent)
+ interpreter.intPool.Put(base, exponent)
return nil, nil
}
-func opSignExtend(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- back := stack.pop()
+func opSignExtend(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ back := stack.Pop()
if back.Cmp(big.NewInt(31)) < 0 {
bit := uint(back.Uint64()*8 + 7)
- num := stack.pop()
+ num := stack.Pop()
mask := back.Lsh(common.Big1, bit)
mask.Sub(mask, common.Big1)
if num.Bit(int(bit)) > 0 {
@@ -162,43 +163,43 @@ func opSignExtend(pc *uint64, interpreter *EVMInterpreter, contract *Contract, m
num.And(num, mask)
}
- stack.push(math.U256(num))
+ stack.Push(math.U256(num))
}
- interpreter.intPool.put(back)
+ interpreter.intPool.Put(back)
return nil, nil
}
-func opNot(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x := stack.peek()
+func opNot(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ x := stack.Peek()
math.U256(x.Not(x))
return nil, nil
}
-func opLt(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.peek()
+func opLt(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ x, y := stack.Pop(), stack.Peek()
if x.Cmp(y) < 0 {
y.SetUint64(1)
} else {
y.SetUint64(0)
}
- interpreter.intPool.put(x)
+ interpreter.intPool.Put(x)
return nil, nil
}
-func opGt(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.peek()
+func opGt(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ x, y := stack.Pop(), stack.Peek()
if x.Cmp(y) > 0 {
y.SetUint64(1)
} else {
y.SetUint64(0)
}
- interpreter.intPool.put(x)
+ interpreter.intPool.Put(x)
return nil, nil
}
-func opSlt(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.peek()
+func opSlt(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ x, y := stack.Pop(), stack.Peek()
xSign := x.Cmp(tt255)
ySign := y.Cmp(tt255)
@@ -217,12 +218,12 @@ func opSlt(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *
y.SetUint64(0)
}
}
- interpreter.intPool.put(x)
+ interpreter.intPool.Put(x)
return nil, nil
}
-func opSgt(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.peek()
+func opSgt(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ x, y := stack.Pop(), stack.Peek()
xSign := x.Cmp(tt255)
ySign := y.Cmp(tt255)
@@ -241,23 +242,23 @@ func opSgt(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *
y.SetUint64(0)
}
}
- interpreter.intPool.put(x)
+ interpreter.intPool.Put(x)
return nil, nil
}
-func opEq(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.peek()
+func opEq(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ x, y := stack.Pop(), stack.Peek()
if x.Cmp(y) == 0 {
y.SetUint64(1)
} else {
y.SetUint64(0)
}
- interpreter.intPool.put(x)
+ interpreter.intPool.Put(x)
return nil, nil
}
-func opIszero(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x := stack.peek()
+func opIszero(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ x := stack.Peek()
if x.Sign() > 0 {
x.SetUint64(0)
} else {
@@ -266,75 +267,75 @@ func opIszero(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor
return nil, nil
}
-func opAnd(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.pop()
- stack.push(x.And(x, y))
+func opAnd(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ x, y := stack.Pop(), stack.Pop()
+ stack.Push(x.And(x, y))
- interpreter.intPool.put(y)
+ interpreter.intPool.Put(y)
return nil, nil
}
-func opOr(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.peek()
+func opOr(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ x, y := stack.Pop(), stack.Peek()
y.Or(x, y)
- interpreter.intPool.put(x)
+ interpreter.intPool.Put(x)
return nil, nil
}
-func opXor(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.peek()
+func opXor(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ x, y := stack.Pop(), stack.Peek()
y.Xor(x, y)
- interpreter.intPool.put(x)
+ interpreter.intPool.Put(x)
return nil, nil
}
-func opByte(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- th, val := stack.pop(), stack.peek()
+func opByte(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ th, val := stack.Pop(), stack.Peek()
if th.Cmp(common.Big32) < 0 {
b := math.Byte(val, 32, int(th.Int64()))
val.SetUint64(uint64(b))
} else {
val.SetUint64(0)
}
- interpreter.intPool.put(th)
+ interpreter.intPool.Put(th)
return nil, nil
}
-func opAddmod(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y, z := stack.pop(), stack.pop(), stack.pop()
+func opAddmod(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ x, y, z := stack.Pop(), stack.Pop(), stack.Pop()
if z.Cmp(bigZero) > 0 {
x.Add(x, y)
x.Mod(x, z)
- stack.push(math.U256(x))
+ stack.Push(math.U256(x))
} else {
- stack.push(x.SetUint64(0))
+ stack.Push(x.SetUint64(0))
}
- interpreter.intPool.put(y, z)
+ interpreter.intPool.Put(y, z)
return nil, nil
}
-func opMulmod(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y, z := stack.pop(), stack.pop(), stack.pop()
+func opMulmod(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ x, y, z := stack.Pop(), stack.Pop(), stack.Pop()
if z.Cmp(bigZero) > 0 {
x.Mul(x, y)
x.Mod(x, z)
- stack.push(math.U256(x))
+ stack.Push(math.U256(x))
} else {
- stack.push(x.SetUint64(0))
+ stack.Push(x.SetUint64(0))
}
- interpreter.intPool.put(y, z)
+ interpreter.intPool.Put(y, z)
return nil, nil
}
// opSHL implements Shift Left
// The SHL instruction (shift left) pops 2 values from the stack, first arg1 and then arg2,
// and pushes on the stack arg2 shifted to the left by arg1 number of bits.
-func opSHL(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+func opSHL(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
// Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards
- shift, value := math.U256(stack.pop()), math.U256(stack.peek())
- defer interpreter.intPool.put(shift) // First operand back into the pool
+ shift, value := math.U256(stack.Pop()), math.U256(stack.Peek())
+ defer interpreter.intPool.Put(shift) // First operand back into the pool
if shift.Cmp(common.Big256) >= 0 {
value.SetUint64(0)
@@ -349,10 +350,10 @@ func opSHL(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *
// opSHR implements Logical Shift Right
// The SHR instruction (logical shift right) pops 2 values from the stack, first arg1 and then arg2,
// and pushes on the stack arg2 shifted to the right by arg1 number of bits with zero fill.
-func opSHR(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+func opSHR(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
// Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards
- shift, value := math.U256(stack.pop()), math.U256(stack.peek())
- defer interpreter.intPool.put(shift) // First operand back into the pool
+ shift, value := math.U256(stack.Pop()), math.U256(stack.Peek())
+ defer interpreter.intPool.Put(shift) // First operand back into the pool
if shift.Cmp(common.Big256) >= 0 {
value.SetUint64(0)
@@ -367,10 +368,10 @@ func opSHR(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *
// opSAR implements Arithmetic Shift Right
// The SAR instruction (arithmetic shift right) pops 2 values from the stack, first arg1 and then arg2,
// and pushes on the stack arg2 shifted to the right by arg1 number of bits with sign extension.
-func opSAR(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+func opSAR(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
// Note, S256 returns (potentially) a new bigint, so we're popping, not peeking this one
- shift, value := math.U256(stack.pop()), math.S256(stack.pop())
- defer interpreter.intPool.put(shift) // First operand back into the pool
+ shift, value := math.U256(stack.Pop()), math.S256(stack.Pop())
+ defer interpreter.intPool.Put(shift) // First operand back into the pool
if shift.Cmp(common.Big256) >= 0 {
if value.Sign() >= 0 {
@@ -378,18 +379,18 @@ func opSAR(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *
} else {
value.SetInt64(-1)
}
- stack.push(math.U256(value))
+ stack.Push(math.U256(value))
return nil, nil
}
n := uint(shift.Uint64())
value.Rsh(value, n)
- stack.push(math.U256(value))
+ stack.Push(math.U256(value))
return nil, nil
}
-func opSha3(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- offset, size := stack.pop(), stack.pop()
+func opSha3(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ offset, size := stack.Pop(), stack.Pop()
data := memory.Get(offset.Int64(), size.Int64())
if interpreter.hasher == nil {
@@ -404,13 +405,13 @@ func opSha3(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
if evm.vmConfig.EnablePreimageRecording {
evm.StateDB.AddPreimage(interpreter.hasherBuf, data)
}
- stack.push(interpreter.intPool.get().SetBytes(interpreter.hasherBuf[:]))
+ stack.Push(interpreter.intPool.Get().SetBytes(interpreter.hasherBuf[:]))
- interpreter.intPool.put(offset, size)
+ interpreter.intPool.Put(offset, size)
return nil, nil
}
-func opRand(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+func opRand(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
evm := interpreter.evm
nonce := evm.StateDB.GetNonce(evm.Origin)
@@ -428,72 +429,72 @@ func opRand(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
binaryOriginNonce,
binaryUsedIndex)
- stack.push(interpreter.intPool.get().SetBytes(hash))
+ stack.Push(interpreter.intPool.Get().SetBytes(hash))
return nil, nil
}
-func opAddress(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(contract.Address().Big())
+func opAddress(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ stack.Push(contract.Address().Big())
return nil, nil
}
-func opBalance(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- slot := stack.peek()
+func opBalance(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ slot := stack.Peek()
slot.Set(interpreter.evm.StateDB.GetBalance(common.BigToAddress(slot)))
return nil, nil
}
-func opOrigin(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.evm.Origin.Big())
+func opOrigin(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ stack.Push(interpreter.evm.Origin.Big())
return nil, nil
}
-func opCaller(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(contract.Caller().Big())
+func opCaller(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ stack.Push(contract.Caller().Big())
return nil, nil
}
-func opCallValue(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.intPool.get().Set(contract.value))
+func opCallValue(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ stack.Push(interpreter.intPool.Get().Set(contract.value))
return nil, nil
}
-func opCallDataLoad(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.intPool.get().SetBytes(getDataBig(contract.Input, stack.pop(), big32)))
+func opCallDataLoad(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ stack.Push(interpreter.intPool.Get().SetBytes(vm.GetDataBig(contract.Input, stack.Pop(), big32)))
return nil, nil
}
-func opCallDataSize(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.intPool.get().SetInt64(int64(len(contract.Input))))
+func opCallDataSize(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ stack.Push(interpreter.intPool.Get().SetInt64(int64(len(contract.Input))))
return nil, nil
}
-func opCallDataCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+func opCallDataCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
var (
- memOffset = stack.pop()
- dataOffset = stack.pop()
- length = stack.pop()
+ memOffset = stack.Pop()
+ dataOffset = stack.Pop()
+ length = stack.Pop()
)
- memory.Set(memOffset.Uint64(), length.Uint64(), getDataBig(contract.Input, dataOffset, length))
+ memory.Set(memOffset.Uint64(), length.Uint64(), vm.GetDataBig(contract.Input, dataOffset, length))
- interpreter.intPool.put(memOffset, dataOffset, length)
+ interpreter.intPool.Put(memOffset, dataOffset, length)
return nil, nil
}
-func opReturnDataSize(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.intPool.get().SetUint64(uint64(len(interpreter.returnData))))
+func opReturnDataSize(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ stack.Push(interpreter.intPool.Get().SetUint64(uint64(len(interpreter.returnData))))
return nil, nil
}
-func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
var (
- memOffset = stack.pop()
- dataOffset = stack.pop()
- length = stack.pop()
+ memOffset = stack.Pop()
+ dataOffset = stack.Pop()
+ length = stack.Pop()
- end = interpreter.intPool.get().Add(dataOffset, length)
+ end = interpreter.intPool.Get().Add(dataOffset, length)
)
- defer interpreter.intPool.put(memOffset, dataOffset, length, end)
+ defer interpreter.intPool.Put(memOffset, dataOffset, length, end)
if end.BitLen() > 64 || uint64(len(interpreter.returnData)) < end.Uint64() {
return nil, errReturnDataOutOfBounds
@@ -503,44 +504,44 @@ func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contrac
return nil, nil
}
-func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- slot := stack.peek()
+func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ slot := stack.Peek()
slot.SetUint64(uint64(interpreter.evm.StateDB.GetCodeSize(common.BigToAddress(slot))))
return nil, nil
}
-func opCodeSize(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- l := interpreter.intPool.get().SetInt64(int64(len(contract.Code)))
- stack.push(l)
+func opCodeSize(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ l := interpreter.intPool.Get().SetInt64(int64(len(contract.Code)))
+ stack.Push(l)
return nil, nil
}
-func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
var (
- memOffset = stack.pop()
- codeOffset = stack.pop()
- length = stack.pop()
+ memOffset = stack.Pop()
+ codeOffset = stack.Pop()
+ length = stack.Pop()
)
- codeCopy := getDataBig(contract.Code, codeOffset, length)
+ codeCopy := vm.GetDataBig(contract.Code, codeOffset, length)
memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy)
- interpreter.intPool.put(memOffset, codeOffset, length)
+ interpreter.intPool.Put(memOffset, codeOffset, length)
return nil, nil
}
-func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
var (
- addr = common.BigToAddress(stack.pop())
- memOffset = stack.pop()
- codeOffset = stack.pop()
- length = stack.pop()
+ addr = common.BigToAddress(stack.Pop())
+ memOffset = stack.Pop()
+ codeOffset = stack.Pop()
+ length = stack.Pop()
)
- codeCopy := getDataBig(interpreter.evm.StateDB.GetCode(addr), codeOffset, length)
+ codeCopy := vm.GetDataBig(interpreter.evm.StateDB.GetCode(addr), codeOffset, length)
memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy)
- interpreter.intPool.put(memOffset, codeOffset, length)
+ interpreter.intPool.Put(memOffset, codeOffset, length)
return nil, nil
}
@@ -570,8 +571,8 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contract,
//
// (6) Caller tries to get the code hash for an account which is marked as deleted,
// this account should be regarded as a non-existent account and zero should be returned.
-func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- slot := stack.peek()
+func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ slot := stack.Peek()
address := common.BigToAddress(slot)
if interpreter.evm.StateDB.Empty(address) {
slot.SetUint64(0)
@@ -581,109 +582,109 @@ func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, contract *Contract,
return nil, nil
}
-func opGasprice(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.intPool.get().Set(interpreter.evm.GasPrice))
+func opGasprice(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ stack.Push(interpreter.intPool.Get().Set(interpreter.evm.GasPrice))
return nil, nil
}
-func opBlockhash(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- num := stack.pop()
+func opBlockhash(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ num := stack.Pop()
- n := interpreter.intPool.get().Sub(interpreter.evm.BlockNumber, common.Big257)
+ n := interpreter.intPool.Get().Sub(interpreter.evm.BlockNumber, common.Big257)
if num.Cmp(n) > 0 && num.Cmp(interpreter.evm.BlockNumber) < 0 {
- stack.push(interpreter.evm.GetHash(num.Uint64()).Big())
+ stack.Push(interpreter.evm.GetHash(num.Uint64()).Big())
} else {
- stack.push(interpreter.intPool.getZero())
+ stack.Push(interpreter.intPool.GetZero())
}
- interpreter.intPool.put(num, n)
+ interpreter.intPool.Put(num, n)
return nil, nil
}
-func opCoinbase(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.evm.Coinbase.Big())
+func opCoinbase(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ stack.Push(interpreter.evm.Coinbase.Big())
return nil, nil
}
-func opTimestamp(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(math.U256(interpreter.intPool.get().Set(interpreter.evm.Time)))
+func opTimestamp(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ stack.Push(math.U256(interpreter.intPool.Get().Set(interpreter.evm.Time)))
return nil, nil
}
-func opNumber(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(math.U256(interpreter.intPool.get().Set(interpreter.evm.BlockNumber)))
+func opNumber(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ stack.Push(math.U256(interpreter.intPool.Get().Set(interpreter.evm.BlockNumber)))
return nil, nil
}
-func opDifficulty(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(math.U256(interpreter.intPool.get().Set(interpreter.evm.Difficulty)))
+func opDifficulty(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ stack.Push(math.U256(interpreter.intPool.Get().Set(interpreter.evm.Difficulty)))
return nil, nil
}
-func opGasLimit(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(math.U256(interpreter.intPool.get().SetUint64(interpreter.evm.GasLimit)))
+func opGasLimit(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ stack.Push(math.U256(interpreter.intPool.Get().SetUint64(interpreter.evm.GasLimit)))
return nil, nil
}
-func opPop(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- interpreter.intPool.put(stack.pop())
+func opPop(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ interpreter.intPool.Put(stack.Pop())
return nil, nil
}
-func opMload(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- offset := stack.pop()
- val := interpreter.intPool.get().SetBytes(memory.Get(offset.Int64(), 32))
- stack.push(val)
+func opMload(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ offset := stack.Pop()
+ val := interpreter.intPool.Get().SetBytes(memory.Get(offset.Int64(), 32))
+ stack.Push(val)
- interpreter.intPool.put(offset)
+ interpreter.intPool.Put(offset)
return nil, nil
}
-func opMstore(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+func opMstore(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
// pop value of the stack
- mStart, val := stack.pop(), stack.pop()
+ mStart, val := stack.Pop(), stack.Pop()
memory.Set32(mStart.Uint64(), val)
- interpreter.intPool.put(mStart, val)
+ interpreter.intPool.Put(mStart, val)
return nil, nil
}
-func opMstore8(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- off, val := stack.pop().Int64(), stack.pop().Int64()
- memory.store[off] = byte(val & 0xff)
+func opMstore8(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ off, val := stack.Pop().Int64(), stack.Pop().Int64()
+ memory.Store[off] = byte(val & 0xff)
return nil, nil
}
-func opSload(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- loc := stack.peek()
+func opSload(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ loc := stack.Peek()
val := interpreter.evm.StateDB.GetState(contract.Address(), common.BigToHash(loc))
loc.SetBytes(val.Bytes())
return nil, nil
}
-func opSstore(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- loc := common.BigToHash(stack.pop())
- val := stack.pop()
+func opSstore(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ loc := common.BigToHash(stack.Pop())
+ val := stack.Pop()
interpreter.evm.StateDB.SetState(contract.Address(), loc, common.BigToHash(val))
- interpreter.intPool.put(val)
+ interpreter.intPool.Put(val)
return nil, nil
}
-func opJump(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- pos := stack.pop()
+func opJump(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ pos := stack.Pop()
if !contract.validJumpdest(pos) {
nop := contract.GetOp(pos.Uint64())
return nil, fmt.Errorf("invalid jump destination (%v) %v", nop, pos)
}
*pc = pos.Uint64()
- interpreter.intPool.put(pos)
+ interpreter.intPool.Put(pos)
return nil, nil
}
-func opJumpi(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- pos, cond := stack.pop(), stack.pop()
+func opJumpi(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ pos, cond := stack.Pop(), stack.Pop()
if cond.Sign() != 0 {
if !contract.validJumpdest(pos) {
nop := contract.GetOp(pos.Uint64())
@@ -694,33 +695,33 @@ func opJumpi(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
*pc++
}
- interpreter.intPool.put(pos, cond)
+ interpreter.intPool.Put(pos, cond)
return nil, nil
}
-func opJumpdest(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+func opJumpdest(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
return nil, nil
}
-func opPc(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.intPool.get().SetUint64(*pc))
+func opPc(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ stack.Push(interpreter.intPool.Get().SetUint64(*pc))
return nil, nil
}
-func opMsize(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.intPool.get().SetInt64(int64(memory.Len())))
+func opMsize(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ stack.Push(interpreter.intPool.Get().SetInt64(int64(memory.Len())))
return nil, nil
}
-func opGas(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.push(interpreter.intPool.get().SetUint64(contract.Gas))
+func opGas(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ stack.Push(interpreter.intPool.Get().SetUint64(contract.Gas))
return nil, nil
}
-func opCreate(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+func opCreate(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
var (
- value = stack.pop()
- offset, size = stack.pop(), stack.pop()
+ value = stack.Pop()
+ offset, size = stack.Pop(), stack.Pop()
input = memory.Get(offset.Int64(), size.Int64())
gas = contract.Gas
)
@@ -734,15 +735,15 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor
// homestead we must check for CodeStoreOutOfGasError (homestead only
// rule) and treat as an error, if the ruleset is frontier we must
// ignore this error and pretend the operation was successful.
- if interpreter.evm.ChainConfig().IsHomestead(interpreter.evm.BlockNumber) && suberr == ErrCodeStoreOutOfGas {
- stack.push(interpreter.intPool.getZero())
- } else if suberr != nil && suberr != ErrCodeStoreOutOfGas {
- stack.push(interpreter.intPool.getZero())
+ if interpreter.evm.ChainConfig().IsHomestead(interpreter.evm.BlockNumber) && suberr == vm.ErrCodeStoreOutOfGas {
+ stack.Push(interpreter.intPool.GetZero())
+ } else if suberr != nil && suberr != vm.ErrCodeStoreOutOfGas {
+ stack.Push(interpreter.intPool.GetZero())
} else {
- stack.push(addr.Big())
+ stack.Push(addr.Big())
}
contract.Gas += returnGas
- interpreter.intPool.put(value, offset, size)
+ interpreter.intPool.Put(value, offset, size)
if suberr == errExecutionReverted {
return res, nil
@@ -750,11 +751,11 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor
return nil, nil
}
-func opCreate2(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+func opCreate2(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
var (
- endowment = stack.pop()
- offset, size = stack.pop(), stack.pop()
- salt = stack.pop()
+ endowment = stack.Pop()
+ offset, size = stack.Pop(), stack.Pop()
+ salt = stack.Pop()
input = memory.Get(offset.Int64(), size.Int64())
gas = contract.Gas
)
@@ -765,12 +766,12 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memo
res, addr, returnGas, suberr := interpreter.evm.Create2(contract, input, gas, endowment, salt)
// Push item on the stack based on the returned error.
if suberr != nil {
- stack.push(interpreter.intPool.getZero())
+ stack.Push(interpreter.intPool.GetZero())
} else {
- stack.push(addr.Big())
+ stack.Push(addr.Big())
}
contract.Gas += returnGas
- interpreter.intPool.put(endowment, offset, size, salt)
+ interpreter.intPool.Put(endowment, offset, size, salt)
if suberr == errExecutionReverted {
return res, nil
@@ -778,12 +779,12 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memo
return nil, nil
}
-func opCall(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+func opCall(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
// Pop gas. The actual gas in interpreter.evm.callGasTemp.
- interpreter.intPool.put(stack.pop())
+ interpreter.intPool.Put(stack.Pop())
gas := interpreter.evm.callGasTemp
// Pop other call parameters.
- addr, value, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
+ addr, value, inOffset, inSize, retOffset, retSize := stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop()
toAddr := common.BigToAddress(addr)
value = math.U256(value)
// Get the arguments from the memory.
@@ -794,25 +795,25 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
}
ret, returnGas, err := interpreter.evm.Call(contract, toAddr, args, gas, value)
if err != nil {
- stack.push(interpreter.intPool.getZero())
+ stack.Push(interpreter.intPool.GetZero())
} else {
- stack.push(interpreter.intPool.get().SetUint64(1))
+ stack.Push(interpreter.intPool.Get().SetUint64(1))
}
if err == nil || err == errExecutionReverted {
memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
}
contract.Gas += returnGas
- interpreter.intPool.put(addr, value, inOffset, inSize, retOffset, retSize)
+ interpreter.intPool.Put(addr, value, inOffset, inSize, retOffset, retSize)
return ret, nil
}
-func opCallCode(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+func opCallCode(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
// Pop gas. The actual gas is in interpreter.evm.callGasTemp.
- interpreter.intPool.put(stack.pop())
+ interpreter.intPool.Put(stack.Pop())
gas := interpreter.evm.callGasTemp
// Pop other call parameters.
- addr, value, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
+ addr, value, inOffset, inSize, retOffset, retSize := stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop()
toAddr := common.BigToAddress(addr)
value = math.U256(value)
// Get arguments from the memory.
@@ -823,92 +824,92 @@ func opCallCode(pc *uint64, interpreter *EVMInterpreter, contract *Contract, mem
}
ret, returnGas, err := interpreter.evm.CallCode(contract, toAddr, args, gas, value)
if err != nil {
- stack.push(interpreter.intPool.getZero())
+ stack.Push(interpreter.intPool.GetZero())
} else {
- stack.push(interpreter.intPool.get().SetUint64(1))
+ stack.Push(interpreter.intPool.Get().SetUint64(1))
}
if err == nil || err == errExecutionReverted {
memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
}
contract.Gas += returnGas
- interpreter.intPool.put(addr, value, inOffset, inSize, retOffset, retSize)
+ interpreter.intPool.Put(addr, value, inOffset, inSize, retOffset, retSize)
return ret, nil
}
-func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
// Pop gas. The actual gas is in interpreter.evm.callGasTemp.
- interpreter.intPool.put(stack.pop())
+ interpreter.intPool.Put(stack.Pop())
gas := interpreter.evm.callGasTemp
// Pop other call parameters.
- addr, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
+ addr, inOffset, inSize, retOffset, retSize := stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop()
toAddr := common.BigToAddress(addr)
// Get arguments from the memory.
args := memory.Get(inOffset.Int64(), inSize.Int64())
ret, returnGas, err := interpreter.evm.DelegateCall(contract, toAddr, args, gas)
if err != nil {
- stack.push(interpreter.intPool.getZero())
+ stack.Push(interpreter.intPool.GetZero())
} else {
- stack.push(interpreter.intPool.get().SetUint64(1))
+ stack.Push(interpreter.intPool.Get().SetUint64(1))
}
if err == nil || err == errExecutionReverted {
memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
}
contract.Gas += returnGas
- interpreter.intPool.put(addr, inOffset, inSize, retOffset, retSize)
+ interpreter.intPool.Put(addr, inOffset, inSize, retOffset, retSize)
return ret, nil
}
-func opStaticCall(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+func opStaticCall(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
// Pop gas. The actual gas is in interpreter.evm.callGasTemp.
- interpreter.intPool.put(stack.pop())
+ interpreter.intPool.Put(stack.Pop())
gas := interpreter.evm.callGasTemp
// Pop other call parameters.
- addr, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
+ addr, inOffset, inSize, retOffset, retSize := stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop()
toAddr := common.BigToAddress(addr)
// Get arguments from the memory.
args := memory.Get(inOffset.Int64(), inSize.Int64())
ret, returnGas, err := interpreter.evm.StaticCall(contract, toAddr, args, gas)
if err != nil {
- stack.push(interpreter.intPool.getZero())
+ stack.Push(interpreter.intPool.GetZero())
} else {
- stack.push(interpreter.intPool.get().SetUint64(1))
+ stack.Push(interpreter.intPool.Get().SetUint64(1))
}
if err == nil || err == errExecutionReverted {
memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
}
contract.Gas += returnGas
- interpreter.intPool.put(addr, inOffset, inSize, retOffset, retSize)
+ interpreter.intPool.Put(addr, inOffset, inSize, retOffset, retSize)
return ret, nil
}
-func opReturn(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- offset, size := stack.pop(), stack.pop()
+func opReturn(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ offset, size := stack.Pop(), stack.Pop()
ret := memory.GetPtr(offset.Int64(), size.Int64())
- interpreter.intPool.put(offset, size)
+ interpreter.intPool.Put(offset, size)
return ret, nil
}
-func opRevert(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- offset, size := stack.pop(), stack.pop()
+func opRevert(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ offset, size := stack.Pop(), stack.Pop()
ret := memory.GetPtr(offset.Int64(), size.Int64())
- interpreter.intPool.put(offset, size)
+ interpreter.intPool.Put(offset, size)
return ret, nil
}
-func opStop(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+func opStop(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
return nil, nil
}
-func opSuicide(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+func opSuicide(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
balance := interpreter.evm.StateDB.GetBalance(contract.Address())
- interpreter.evm.StateDB.AddBalance(common.BigToAddress(stack.pop()), balance)
+ interpreter.evm.StateDB.AddBalance(common.BigToAddress(stack.Pop()), balance)
interpreter.evm.StateDB.Suicide(contract.Address())
return nil, nil
@@ -918,11 +919,11 @@ func opSuicide(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memo
// make log instruction function
func makeLog(size int) executionFunc {
- return func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+ return func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
topics := make([]common.Hash, size)
- mStart, mSize := stack.pop(), stack.pop()
+ mStart, mSize := stack.Pop(), stack.Pop()
for i := 0; i < size; i++ {
- topics[i] = common.BigToHash(stack.pop())
+ topics[i] = common.BigToHash(stack.Pop())
}
d := memory.Get(mStart.Int64(), mSize.Int64())
@@ -935,14 +936,14 @@ func makeLog(size int) executionFunc {
BlockNumber: interpreter.evm.BlockNumber.Uint64(),
})
- interpreter.intPool.put(mStart, mSize)
+ interpreter.intPool.Put(mStart, mSize)
return nil, nil
}
}
// make push instruction function
func makePush(size uint64, pushByteSize int) executionFunc {
- return func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
+ return func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
codeLen := len(contract.Code)
startMin := codeLen
@@ -955,8 +956,8 @@ func makePush(size uint64, pushByteSize int) executionFunc {
endMin = startMin + pushByteSize
}
- integer := interpreter.intPool.get()
- stack.push(integer.SetBytes(common.RightPadBytes(contract.Code[startMin:endMin], pushByteSize)))
+ integer := interpreter.intPool.Get()
+ stack.Push(integer.SetBytes(common.RightPadBytes(contract.Code[startMin:endMin], pushByteSize)))
*pc += size
return nil, nil
@@ -965,8 +966,8 @@ func makePush(size uint64, pushByteSize int) executionFunc {
// make dup instruction function
func makeDup(size int64) executionFunc {
- return func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.dup(interpreter.intPool, int(size))
+ return func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ stack.Dup(interpreter.intPool, int(size))
return nil, nil
}
}
@@ -975,8 +976,8 @@ func makeDup(size int64) executionFunc {
func makeSwap(size int64) executionFunc {
// switch n + 1 otherwise n would be swapped with n
size++
- return func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- stack.swap(int(size))
+ return func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ stack.Swap(int(size))
return nil, nil
}
}
diff --git a/core/vm/instructions_test.go b/core/vm/evm/instructions_test.go
index 04c03e1a6..9e677dde3 100644
--- a/core/vm/instructions_test.go
+++ b/core/vm/evm/instructions_test.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package vm
+package evm
import (
"bytes"
@@ -22,6 +22,7 @@ import (
"testing"
"github.com/dexon-foundation/dexon/common"
+ "github.com/dexon-foundation/dexon/core/vm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/params"
)
@@ -32,37 +33,37 @@ type twoOperandTest struct {
expected string
}
-func testTwoOperandOp(t *testing.T, tests []twoOperandTest, opFn func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error)) {
+func testTwoOperandOp(t *testing.T, tests []twoOperandTest, opFn func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error)) {
var (
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
- stack = newstack()
+ stack = NewStack()
pc = uint64(0)
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
)
env.interpreter = evmInterpreter
- evmInterpreter.intPool = poolOfIntPools.get()
+ evmInterpreter.intPool = vm.PoolOfIntPools.Get()
for i, test := range tests {
x := new(big.Int).SetBytes(common.Hex2Bytes(test.x))
shift := new(big.Int).SetBytes(common.Hex2Bytes(test.y))
expected := new(big.Int).SetBytes(common.Hex2Bytes(test.expected))
- stack.push(x)
- stack.push(shift)
+ stack.Push(x)
+ stack.Push(shift)
opFn(&pc, evmInterpreter, nil, nil, stack)
- actual := stack.pop()
+ actual := stack.Pop()
if actual.Cmp(expected) != 0 {
t.Errorf("Testcase %d, expected %v, got %v", i, expected, actual)
}
// Check pool usage
// 1.pool is not allowed to contain anything on the stack
// 2.pool is not allowed to contain the same pointers twice
- if evmInterpreter.intPool.pool.len() > 0 {
+ if evmInterpreter.intPool.Pool.Len() > 0 {
poolvals := make(map[*big.Int]struct{})
poolvals[actual] = struct{}{}
- for evmInterpreter.intPool.pool.len() > 0 {
- key := evmInterpreter.intPool.get()
+ for evmInterpreter.intPool.Pool.Len() > 0 {
+ key := evmInterpreter.intPool.Get()
if _, exist := poolvals[key]; exist {
t.Errorf("Testcase %d, pool contains double-entry", i)
}
@@ -70,18 +71,18 @@ func testTwoOperandOp(t *testing.T, tests []twoOperandTest, opFn func(pc *uint64
}
}
}
- poolOfIntPools.put(evmInterpreter.intPool)
+ vm.PoolOfIntPools.Put(evmInterpreter.intPool)
}
func TestByteOp(t *testing.T) {
var (
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
- stack = newstack()
+ stack = NewStack()
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
)
env.interpreter = evmInterpreter
- evmInterpreter.intPool = poolOfIntPools.get()
+ evmInterpreter.intPool = vm.PoolOfIntPools.Get()
tests := []struct {
v string
th uint64
@@ -100,15 +101,15 @@ func TestByteOp(t *testing.T) {
for _, test := range tests {
val := new(big.Int).SetBytes(common.Hex2Bytes(test.v))
th := new(big.Int).SetUint64(test.th)
- stack.push(val)
- stack.push(th)
+ stack.Push(val)
+ stack.Push(th)
opByte(&pc, evmInterpreter, nil, nil, stack)
- actual := stack.pop()
+ actual := stack.Pop()
if actual.Cmp(test.expected) != 0 {
t.Fatalf("Expected [%v] %v:th byte to be %v, was %v.", test.v, test.th, test.expected, actual)
}
}
- poolOfIntPools.put(evmInterpreter.intPool)
+ vm.PoolOfIntPools.Put(evmInterpreter.intPool)
}
func TestSHL(t *testing.T) {
@@ -208,15 +209,15 @@ func TestSLT(t *testing.T) {
testTwoOperandOp(t, tests, opSlt)
}
-func opBenchmark(bench *testing.B, op func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error), args ...string) {
+func opBenchmark(bench *testing.B, op func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error), args ...string) {
var (
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
- stack = newstack()
+ stack = NewStack()
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
)
env.interpreter = evmInterpreter
- evmInterpreter.intPool = poolOfIntPools.get()
+ evmInterpreter.intPool = vm.PoolOfIntPools.Get()
// convert args
byteArgs := make([][]byte, len(args))
for i, arg := range args {
@@ -227,12 +228,12 @@ func opBenchmark(bench *testing.B, op func(pc *uint64, interpreter *EVMInterpret
for i := 0; i < bench.N; i++ {
for _, arg := range byteArgs {
a := new(big.Int).SetBytes(arg)
- stack.push(a)
+ stack.Push(a)
}
op(&pc, evmInterpreter, nil, nil, stack)
- stack.pop()
+ stack.Pop()
}
- poolOfIntPools.put(evmInterpreter.intPool)
+ vm.PoolOfIntPools.Put(evmInterpreter.intPool)
}
func BenchmarkOpAdd64(b *testing.B) {
@@ -446,39 +447,39 @@ func BenchmarkOpIsZero(b *testing.B) {
func TestOpMstore(t *testing.T) {
var (
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
- stack = newstack()
- mem = NewMemory()
+ stack = NewStack()
+ mem = vm.NewMemory()
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
)
env.interpreter = evmInterpreter
- evmInterpreter.intPool = poolOfIntPools.get()
+ evmInterpreter.intPool = vm.PoolOfIntPools.Get()
mem.Resize(64)
pc := uint64(0)
v := "abcdef00000000000000abba000000000deaf000000c0de00100000000133700"
- stack.pushN(new(big.Int).SetBytes(common.Hex2Bytes(v)), big.NewInt(0))
+ stack.PushN(new(big.Int).SetBytes(common.Hex2Bytes(v)), big.NewInt(0))
opMstore(&pc, evmInterpreter, nil, mem, stack)
if got := common.Bytes2Hex(mem.Get(0, 32)); got != v {
t.Fatalf("Mstore fail, got %v, expected %v", got, v)
}
- stack.pushN(big.NewInt(0x1), big.NewInt(0))
+ stack.PushN(big.NewInt(0x1), big.NewInt(0))
opMstore(&pc, evmInterpreter, nil, mem, stack)
if common.Bytes2Hex(mem.Get(0, 32)) != "0000000000000000000000000000000000000000000000000000000000000001" {
t.Fatalf("Mstore failed to overwrite previous value")
}
- poolOfIntPools.put(evmInterpreter.intPool)
+ vm.PoolOfIntPools.Put(evmInterpreter.intPool)
}
func BenchmarkOpMstore(bench *testing.B) {
var (
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
- stack = newstack()
- mem = NewMemory()
+ stack = NewStack()
+ mem = vm.NewMemory()
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
)
env.interpreter = evmInterpreter
- evmInterpreter.intPool = poolOfIntPools.get()
+ evmInterpreter.intPool = vm.PoolOfIntPools.Get()
mem.Resize(64)
pc := uint64(0)
memStart := big.NewInt(0)
@@ -486,31 +487,31 @@ func BenchmarkOpMstore(bench *testing.B) {
bench.ResetTimer()
for i := 0; i < bench.N; i++ {
- stack.pushN(value, memStart)
+ stack.PushN(value, memStart)
opMstore(&pc, evmInterpreter, nil, mem, stack)
}
- poolOfIntPools.put(evmInterpreter.intPool)
+ vm.PoolOfIntPools.Put(evmInterpreter.intPool)
}
func BenchmarkOpSHA3(bench *testing.B) {
var (
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
- stack = newstack()
- mem = NewMemory()
+ stack = NewStack()
+ mem = vm.NewMemory()
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
)
env.interpreter = evmInterpreter
- evmInterpreter.intPool = poolOfIntPools.get()
+ evmInterpreter.intPool = vm.PoolOfIntPools.Get()
mem.Resize(32)
pc := uint64(0)
start := big.NewInt(0)
bench.ResetTimer()
for i := 0; i < bench.N; i++ {
- stack.pushN(big.NewInt(32), start)
+ stack.PushN(big.NewInt(32), start)
opSha3(&pc, evmInterpreter, nil, mem, stack)
}
- poolOfIntPools.put(evmInterpreter.intPool)
+ vm.PoolOfIntPools.Put(evmInterpreter.intPool)
}
func TestCreate2Addreses(t *testing.T) {
@@ -572,11 +573,11 @@ func TestCreate2Addreses(t *testing.T) {
codeHash := crypto.Keccak256(code)
address := crypto.CreateAddress2(origin, salt, codeHash)
/*
- stack := newstack()
+ stack := NewStack()
// salt, but we don't need that for this test
- stack.push(big.NewInt(int64(len(code)))) //size
- stack.push(big.NewInt(0)) // memstart
- stack.push(big.NewInt(0)) // value
+ stack.Push(big.NewInt(int64(len(code)))) //size
+ stack.Push(big.NewInt(0)) // memstart
+ stack.Push(big.NewInt(0)) // value
gas, _ := gasCreate2(params.GasTable{}, nil, nil, stack, nil, 0)
fmt.Printf("Example %d\n* address `0x%x`\n* salt `0x%x`\n* init_code `0x%x`\n* gas (assuming no mem expansion): `%v`\n* result: `%s`\n\n", i,origin, salt, code, gas, address.String())
*/
diff --git a/core/vm/interface.go b/core/vm/evm/interface.go
index 3e86a4ff2..20e5f34a9 100644
--- a/core/vm/interface.go
+++ b/core/vm/evm/interface.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package vm
+package evm
import (
"math/big"
diff --git a/core/vm/interpreter.go b/core/vm/evm/interpreter.go
index ffe5ff626..ca3ddd05a 100644
--- a/core/vm/interpreter.go
+++ b/core/vm/evm/interpreter.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package vm
+package evm
import (
"fmt"
@@ -23,6 +23,7 @@ import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/common/math"
+ "github.com/dexon-foundation/dexon/core/vm"
"github.com/dexon-foundation/dexon/params"
)
@@ -87,7 +88,7 @@ type EVMInterpreter struct {
cfg Config
gasTable params.GasTable
- intPool *intPool
+ intPool *vm.IntPool
hasher keccakState // Keccak256 hasher instance shared across opcodes
hasherBuf common.Hash // Keccak256 hasher result array shared aross opcodes
@@ -121,7 +122,7 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
}
}
-func (in *EVMInterpreter) enforceRestrictions(op OpCode, operation operation, stack *Stack) error {
+func (in *EVMInterpreter) enforceRestrictions(op OpCode, operation operation, stack *vm.Stack) error {
if in.evm.chainRules.IsByzantium {
if in.readOnly {
// If the interpreter is operating in readonly mode, make sure no
@@ -145,9 +146,9 @@ func (in *EVMInterpreter) enforceRestrictions(op OpCode, operation operation, st
// errExecutionReverted which means revert-and-keep-gas-left.
func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (ret []byte, err error) {
if in.intPool == nil {
- in.intPool = poolOfIntPools.get()
+ in.intPool = vm.PoolOfIntPools.Get()
defer func() {
- poolOfIntPools.put(in.intPool)
+ vm.PoolOfIntPools.Put(in.intPool)
in.intPool = nil
}()
}
@@ -173,9 +174,9 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
}
var (
- op OpCode // current opcode
- mem = NewMemory() // bound memory
- stack = newstack() // local stack
+ op OpCode // current opcode
+ mem = vm.NewMemory() // bound memory
+ stack = NewStack() // local stack
// For optimisation reason we're using uint64 as the program counter.
// It's theoretically possible to go above 2^64. The YP defines the PC
// to be uint256. Practically much less so feasible.
@@ -190,8 +191,8 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
// Reclaim the stack as an int pool when the execution stops
defer func() {
- in.intPool.put(stack.data...)
- recyclestack(stack)
+ in.intPool.Put(stack.Data...)
+ Recyclestack(stack)
}()
if in.cfg.Debug {
@@ -234,13 +235,13 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
// calculate the new memory size and expand the memory to fit
// the operation
if operation.memorySize != nil {
- memSize, overflow := bigUint64(operation.memorySize(stack))
+ memSize, overflow := vm.BigUint64(operation.memorySize(stack))
if overflow {
return nil, errGasUintOverflow
}
// memory is expanded in words of 32 bytes. Gas
// is also calculated in words.
- if memorySize, overflow = math.SafeMul(toWordSize(memSize), 32); overflow {
+ if memorySize, overflow = math.SafeMul(vm.ToWordSize(memSize), 32); overflow {
return nil, errGasUintOverflow
}
}
@@ -248,7 +249,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
// cost is explicitly set so that the capture state defer method can get the proper cost
cost, err = operation.gasCost(in.gasTable, in.evm, contract, stack, mem, memorySize)
if err != nil || !contract.UseGas(cost) {
- return nil, ErrOutOfGas
+ return nil, vm.ErrOutOfGas
}
if memorySize > 0 {
mem.Resize(memorySize)
@@ -263,8 +264,8 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
res, err := operation.execute(&pc, in, contract, mem, stack)
// verifyPool is a build flag. Pool verification makes sure the integrity
// of the integer pool by comparing values to a default value.
- if verifyPool {
- verifyIntegerPool(in.intPool)
+ if vm.VerifyPool {
+ vm.VerifyIntegerPool(in.intPool)
}
// if the operation clears the return data (e.g. it has returning data)
// set the last return to the result of the operation.
diff --git a/core/vm/jump_table.go b/core/vm/evm/jump_table.go
index 608e34419..da2f50c5a 100644
--- a/core/vm/jump_table.go
+++ b/core/vm/evm/jump_table.go
@@ -14,20 +14,20 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package vm
+package evm
import (
"errors"
"math/big"
+ "github.com/dexon-foundation/dexon/core/vm"
"github.com/dexon-foundation/dexon/params"
)
type (
- executionFunc func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error)
- gasFunc func(params.GasTable, *EVM, *Contract, *Stack, *Memory, uint64) (uint64, error) // last parameter is the requested memory size as a uint64
- stackValidationFunc func(*Stack) error
- memorySizeFunc func(*Stack) *big.Int
+ executionFunc func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error)
+ gasFunc func(params.GasTable, *EVM, *Contract, *vm.Stack, *vm.Memory, uint64) (uint64, error) // last parameter is the requested memory size as a uint64
+ memorySizeFunc func(*vm.Stack) *big.Int
)
var errGasUintOverflow = errors.New("gas uint64 overflow")
@@ -38,7 +38,7 @@ type operation struct {
// gasCost is the gas function and returns the gas required for execution
gasCost gasFunc
// validateStack validates the stack (size) for the operation
- validateStack stackValidationFunc
+ validateStack vm.StackValidationFunc
// memorySize returns the memory size required for the operation
memorySize memorySizeFunc
@@ -65,31 +65,31 @@ func newConstantinopleInstructionSet() [256]operation {
instructionSet[SHL] = operation{
execute: opSHL,
gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
+ validateStack: vm.MakeStackFunc(2, 1),
valid: true,
}
instructionSet[SHR] = operation{
execute: opSHR,
gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
+ validateStack: vm.MakeStackFunc(2, 1),
valid: true,
}
instructionSet[SAR] = operation{
execute: opSAR,
gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
+ validateStack: vm.MakeStackFunc(2, 1),
valid: true,
}
instructionSet[EXTCODEHASH] = operation{
execute: opExtCodeHash,
gasCost: gasExtCodeHash,
- validateStack: makeStackFunc(1, 1),
+ validateStack: vm.MakeStackFunc(1, 1),
valid: true,
}
instructionSet[CREATE2] = operation{
execute: opCreate2,
gasCost: gasCreate2,
- validateStack: makeStackFunc(4, 1),
+ validateStack: vm.MakeStackFunc(4, 1),
memorySize: memoryCreate2,
valid: true,
writes: true,
@@ -106,7 +106,7 @@ func newByzantiumInstructionSet() [256]operation {
instructionSet[STATICCALL] = operation{
execute: opStaticCall,
gasCost: gasStaticCall,
- validateStack: makeStackFunc(6, 1),
+ validateStack: vm.MakeStackFunc(6, 1),
memorySize: memoryStaticCall,
valid: true,
returns: true,
@@ -114,20 +114,20 @@ func newByzantiumInstructionSet() [256]operation {
instructionSet[RETURNDATASIZE] = operation{
execute: opReturnDataSize,
gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
}
instructionSet[RETURNDATACOPY] = operation{
execute: opReturnDataCopy,
gasCost: gasReturnDataCopy,
- validateStack: makeStackFunc(3, 0),
+ validateStack: vm.MakeStackFunc(3, 0),
memorySize: memoryReturnDataCopy,
valid: true,
}
instructionSet[REVERT] = operation{
execute: opRevert,
gasCost: gasRevert,
- validateStack: makeStackFunc(2, 0),
+ validateStack: vm.MakeStackFunc(2, 0),
memorySize: memoryRevert,
valid: true,
reverts: true,
@@ -143,7 +143,7 @@ func newHomesteadInstructionSet() [256]operation {
instructionSet[DELEGATECALL] = operation{
execute: opDelegateCall,
gasCost: gasDelegateCall,
- validateStack: makeStackFunc(6, 1),
+ validateStack: vm.MakeStackFunc(6, 1),
memorySize: memoryDelegateCall,
valid: true,
returns: true,
@@ -158,289 +158,289 @@ func newFrontierInstructionSet() [256]operation {
STOP: {
execute: opStop,
gasCost: constGasFunc(0),
- validateStack: makeStackFunc(0, 0),
+ validateStack: vm.MakeStackFunc(0, 0),
halts: true,
valid: true,
},
ADD: {
execute: opAdd,
gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
+ validateStack: vm.MakeStackFunc(2, 1),
valid: true,
},
MUL: {
execute: opMul,
gasCost: constGasFunc(GasFastStep),
- validateStack: makeStackFunc(2, 1),
+ validateStack: vm.MakeStackFunc(2, 1),
valid: true,
},
SUB: {
execute: opSub,
gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
+ validateStack: vm.MakeStackFunc(2, 1),
valid: true,
},
DIV: {
execute: opDiv,
gasCost: constGasFunc(GasFastStep),
- validateStack: makeStackFunc(2, 1),
+ validateStack: vm.MakeStackFunc(2, 1),
valid: true,
},
SDIV: {
execute: opSdiv,
gasCost: constGasFunc(GasFastStep),
- validateStack: makeStackFunc(2, 1),
+ validateStack: vm.MakeStackFunc(2, 1),
valid: true,
},
MOD: {
execute: opMod,
gasCost: constGasFunc(GasFastStep),
- validateStack: makeStackFunc(2, 1),
+ validateStack: vm.MakeStackFunc(2, 1),
valid: true,
},
SMOD: {
execute: opSmod,
gasCost: constGasFunc(GasFastStep),
- validateStack: makeStackFunc(2, 1),
+ validateStack: vm.MakeStackFunc(2, 1),
valid: true,
},
ADDMOD: {
execute: opAddmod,
gasCost: constGasFunc(GasMidStep),
- validateStack: makeStackFunc(3, 1),
+ validateStack: vm.MakeStackFunc(3, 1),
valid: true,
},
MULMOD: {
execute: opMulmod,
gasCost: constGasFunc(GasMidStep),
- validateStack: makeStackFunc(3, 1),
+ validateStack: vm.MakeStackFunc(3, 1),
valid: true,
},
EXP: {
execute: opExp,
gasCost: gasExp,
- validateStack: makeStackFunc(2, 1),
+ validateStack: vm.MakeStackFunc(2, 1),
valid: true,
},
SIGNEXTEND: {
execute: opSignExtend,
gasCost: constGasFunc(GasFastStep),
- validateStack: makeStackFunc(2, 1),
+ validateStack: vm.MakeStackFunc(2, 1),
valid: true,
},
LT: {
execute: opLt,
gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
+ validateStack: vm.MakeStackFunc(2, 1),
valid: true,
},
GT: {
execute: opGt,
gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
+ validateStack: vm.MakeStackFunc(2, 1),
valid: true,
},
SLT: {
execute: opSlt,
gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
+ validateStack: vm.MakeStackFunc(2, 1),
valid: true,
},
SGT: {
execute: opSgt,
gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
+ validateStack: vm.MakeStackFunc(2, 1),
valid: true,
},
EQ: {
execute: opEq,
gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
+ validateStack: vm.MakeStackFunc(2, 1),
valid: true,
},
ISZERO: {
execute: opIszero,
gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(1, 1),
+ validateStack: vm.MakeStackFunc(1, 1),
valid: true,
},
AND: {
execute: opAnd,
gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
+ validateStack: vm.MakeStackFunc(2, 1),
valid: true,
},
XOR: {
execute: opXor,
gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
+ validateStack: vm.MakeStackFunc(2, 1),
valid: true,
},
OR: {
execute: opOr,
gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
+ validateStack: vm.MakeStackFunc(2, 1),
valid: true,
},
NOT: {
execute: opNot,
gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(1, 1),
+ validateStack: vm.MakeStackFunc(1, 1),
valid: true,
},
BYTE: {
execute: opByte,
gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(2, 1),
+ validateStack: vm.MakeStackFunc(2, 1),
valid: true,
},
SHA3: {
execute: opSha3,
gasCost: gasSha3,
- validateStack: makeStackFunc(2, 1),
+ validateStack: vm.MakeStackFunc(2, 1),
memorySize: memorySha3,
valid: true,
},
RAND: {
execute: opRand,
gasCost: constGasFunc(params.RandGas),
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
ADDRESS: {
execute: opAddress,
gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
BALANCE: {
execute: opBalance,
gasCost: gasBalance,
- validateStack: makeStackFunc(1, 1),
+ validateStack: vm.MakeStackFunc(1, 1),
valid: true,
},
ORIGIN: {
execute: opOrigin,
gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
CALLER: {
execute: opCaller,
gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
CALLVALUE: {
execute: opCallValue,
gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
CALLDATALOAD: {
execute: opCallDataLoad,
gasCost: constGasFunc(GasFastestStep),
- validateStack: makeStackFunc(1, 1),
+ validateStack: vm.MakeStackFunc(1, 1),
valid: true,
},
CALLDATASIZE: {
execute: opCallDataSize,
gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
CALLDATACOPY: {
execute: opCallDataCopy,
gasCost: gasCallDataCopy,
- validateStack: makeStackFunc(3, 0),
+ validateStack: vm.MakeStackFunc(3, 0),
memorySize: memoryCallDataCopy,
valid: true,
},
CODESIZE: {
execute: opCodeSize,
gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
CODECOPY: {
execute: opCodeCopy,
gasCost: gasCodeCopy,
- validateStack: makeStackFunc(3, 0),
+ validateStack: vm.MakeStackFunc(3, 0),
memorySize: memoryCodeCopy,
valid: true,
},
GASPRICE: {
execute: opGasprice,
gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
EXTCODESIZE: {
execute: opExtCodeSize,
gasCost: gasExtCodeSize,
- validateStack: makeStackFunc(1, 1),
+ validateStack: vm.MakeStackFunc(1, 1),
valid: true,
},
EXTCODECOPY: {
execute: opExtCodeCopy,
gasCost: gasExtCodeCopy,
- validateStack: makeStackFunc(4, 0),
+ validateStack: vm.MakeStackFunc(4, 0),
memorySize: memoryExtCodeCopy,
valid: true,
},
BLOCKHASH: {
execute: opBlockhash,
gasCost: constGasFunc(GasExtStep),
- validateStack: makeStackFunc(1, 1),
+ validateStack: vm.MakeStackFunc(1, 1),
valid: true,
},
COINBASE: {
execute: opCoinbase,
gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
TIMESTAMP: {
execute: opTimestamp,
gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
NUMBER: {
execute: opNumber,
gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
DIFFICULTY: {
execute: opDifficulty,
gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
GASLIMIT: {
execute: opGasLimit,
gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
POP: {
execute: opPop,
gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(1, 0),
+ validateStack: vm.MakeStackFunc(1, 0),
valid: true,
},
MLOAD: {
execute: opMload,
gasCost: gasMLoad,
- validateStack: makeStackFunc(1, 1),
+ validateStack: vm.MakeStackFunc(1, 1),
memorySize: memoryMLoad,
valid: true,
},
MSTORE: {
execute: opMstore,
gasCost: gasMStore,
- validateStack: makeStackFunc(2, 0),
+ validateStack: vm.MakeStackFunc(2, 0),
memorySize: memoryMStore,
valid: true,
},
@@ -448,449 +448,449 @@ func newFrontierInstructionSet() [256]operation {
execute: opMstore8,
gasCost: gasMStore8,
memorySize: memoryMStore8,
- validateStack: makeStackFunc(2, 0),
+ validateStack: vm.MakeStackFunc(2, 0),
valid: true,
},
SLOAD: {
execute: opSload,
gasCost: gasSLoad,
- validateStack: makeStackFunc(1, 1),
+ validateStack: vm.MakeStackFunc(1, 1),
valid: true,
},
SSTORE: {
execute: opSstore,
gasCost: gasSStore,
- validateStack: makeStackFunc(2, 0),
+ validateStack: vm.MakeStackFunc(2, 0),
valid: true,
writes: true,
},
JUMP: {
execute: opJump,
gasCost: constGasFunc(GasMidStep),
- validateStack: makeStackFunc(1, 0),
+ validateStack: vm.MakeStackFunc(1, 0),
jumps: true,
valid: true,
},
JUMPI: {
execute: opJumpi,
gasCost: constGasFunc(GasSlowStep),
- validateStack: makeStackFunc(2, 0),
+ validateStack: vm.MakeStackFunc(2, 0),
jumps: true,
valid: true,
},
PC: {
execute: opPc,
gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
MSIZE: {
execute: opMsize,
gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
GAS: {
execute: opGas,
gasCost: constGasFunc(GasQuickStep),
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
JUMPDEST: {
execute: opJumpdest,
gasCost: constGasFunc(params.JumpdestGas),
- validateStack: makeStackFunc(0, 0),
+ validateStack: vm.MakeStackFunc(0, 0),
valid: true,
},
PUSH1: {
execute: makePush(1, 1),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH2: {
execute: makePush(2, 2),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH3: {
execute: makePush(3, 3),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH4: {
execute: makePush(4, 4),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH5: {
execute: makePush(5, 5),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH6: {
execute: makePush(6, 6),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH7: {
execute: makePush(7, 7),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH8: {
execute: makePush(8, 8),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH9: {
execute: makePush(9, 9),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH10: {
execute: makePush(10, 10),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH11: {
execute: makePush(11, 11),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH12: {
execute: makePush(12, 12),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH13: {
execute: makePush(13, 13),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH14: {
execute: makePush(14, 14),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH15: {
execute: makePush(15, 15),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH16: {
execute: makePush(16, 16),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH17: {
execute: makePush(17, 17),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH18: {
execute: makePush(18, 18),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH19: {
execute: makePush(19, 19),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH20: {
execute: makePush(20, 20),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH21: {
execute: makePush(21, 21),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH22: {
execute: makePush(22, 22),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH23: {
execute: makePush(23, 23),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH24: {
execute: makePush(24, 24),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH25: {
execute: makePush(25, 25),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH26: {
execute: makePush(26, 26),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH27: {
execute: makePush(27, 27),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH28: {
execute: makePush(28, 28),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH29: {
execute: makePush(29, 29),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH30: {
execute: makePush(30, 30),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH31: {
execute: makePush(31, 31),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
PUSH32: {
execute: makePush(32, 32),
gasCost: gasPush,
- validateStack: makeStackFunc(0, 1),
+ validateStack: vm.MakeStackFunc(0, 1),
valid: true,
},
DUP1: {
execute: makeDup(1),
gasCost: gasDup,
- validateStack: makeDupStackFunc(1),
+ validateStack: vm.MakeDupStackFunc(1),
valid: true,
},
DUP2: {
execute: makeDup(2),
gasCost: gasDup,
- validateStack: makeDupStackFunc(2),
+ validateStack: vm.MakeDupStackFunc(2),
valid: true,
},
DUP3: {
execute: makeDup(3),
gasCost: gasDup,
- validateStack: makeDupStackFunc(3),
+ validateStack: vm.MakeDupStackFunc(3),
valid: true,
},
DUP4: {
execute: makeDup(4),
gasCost: gasDup,
- validateStack: makeDupStackFunc(4),
+ validateStack: vm.MakeDupStackFunc(4),
valid: true,
},
DUP5: {
execute: makeDup(5),
gasCost: gasDup,
- validateStack: makeDupStackFunc(5),
+ validateStack: vm.MakeDupStackFunc(5),
valid: true,
},
DUP6: {
execute: makeDup(6),
gasCost: gasDup,
- validateStack: makeDupStackFunc(6),
+ validateStack: vm.MakeDupStackFunc(6),
valid: true,
},
DUP7: {
execute: makeDup(7),
gasCost: gasDup,
- validateStack: makeDupStackFunc(7),
+ validateStack: vm.MakeDupStackFunc(7),
valid: true,
},
DUP8: {
execute: makeDup(8),
gasCost: gasDup,
- validateStack: makeDupStackFunc(8),
+ validateStack: vm.MakeDupStackFunc(8),
valid: true,
},
DUP9: {
execute: makeDup(9),
gasCost: gasDup,
- validateStack: makeDupStackFunc(9),
+ validateStack: vm.MakeDupStackFunc(9),
valid: true,
},
DUP10: {
execute: makeDup(10),
gasCost: gasDup,
- validateStack: makeDupStackFunc(10),
+ validateStack: vm.MakeDupStackFunc(10),
valid: true,
},
DUP11: {
execute: makeDup(11),
gasCost: gasDup,
- validateStack: makeDupStackFunc(11),
+ validateStack: vm.MakeDupStackFunc(11),
valid: true,
},
DUP12: {
execute: makeDup(12),
gasCost: gasDup,
- validateStack: makeDupStackFunc(12),
+ validateStack: vm.MakeDupStackFunc(12),
valid: true,
},
DUP13: {
execute: makeDup(13),
gasCost: gasDup,
- validateStack: makeDupStackFunc(13),
+ validateStack: vm.MakeDupStackFunc(13),
valid: true,
},
DUP14: {
execute: makeDup(14),
gasCost: gasDup,
- validateStack: makeDupStackFunc(14),
+ validateStack: vm.MakeDupStackFunc(14),
valid: true,
},
DUP15: {
execute: makeDup(15),
gasCost: gasDup,
- validateStack: makeDupStackFunc(15),
+ validateStack: vm.MakeDupStackFunc(15),
valid: true,
},
DUP16: {
execute: makeDup(16),
gasCost: gasDup,
- validateStack: makeDupStackFunc(16),
+ validateStack: vm.MakeDupStackFunc(16),
valid: true,
},
SWAP1: {
execute: makeSwap(1),
gasCost: gasSwap,
- validateStack: makeSwapStackFunc(2),
+ validateStack: vm.MakeSwapStackFunc(2),
valid: true,
},
SWAP2: {
execute: makeSwap(2),
gasCost: gasSwap,
- validateStack: makeSwapStackFunc(3),
+ validateStack: vm.MakeSwapStackFunc(3),
valid: true,
},
SWAP3: {
execute: makeSwap(3),
gasCost: gasSwap,
- validateStack: makeSwapStackFunc(4),
+ validateStack: vm.MakeSwapStackFunc(4),
valid: true,
},
SWAP4: {
execute: makeSwap(4),
gasCost: gasSwap,
- validateStack: makeSwapStackFunc(5),
+ validateStack: vm.MakeSwapStackFunc(5),
valid: true,
},
SWAP5: {
execute: makeSwap(5),
gasCost: gasSwap,
- validateStack: makeSwapStackFunc(6),
+ validateStack: vm.MakeSwapStackFunc(6),
valid: true,
},
SWAP6: {
execute: makeSwap(6),
gasCost: gasSwap,
- validateStack: makeSwapStackFunc(7),
+ validateStack: vm.MakeSwapStackFunc(7),
valid: true,
},
SWAP7: {
execute: makeSwap(7),
gasCost: gasSwap,
- validateStack: makeSwapStackFunc(8),
+ validateStack: vm.MakeSwapStackFunc(8),
valid: true,
},
SWAP8: {
execute: makeSwap(8),
gasCost: gasSwap,
- validateStack: makeSwapStackFunc(9),
+ validateStack: vm.MakeSwapStackFunc(9),
valid: true,
},
SWAP9: {
execute: makeSwap(9),
gasCost: gasSwap,
- validateStack: makeSwapStackFunc(10),
+ validateStack: vm.MakeSwapStackFunc(10),
valid: true,
},
SWAP10: {
execute: makeSwap(10),
gasCost: gasSwap,
- validateStack: makeSwapStackFunc(11),
+ validateStack: vm.MakeSwapStackFunc(11),
valid: true,
},
SWAP11: {
execute: makeSwap(11),
gasCost: gasSwap,
- validateStack: makeSwapStackFunc(12),
+ validateStack: vm.MakeSwapStackFunc(12),
valid: true,
},
SWAP12: {
execute: makeSwap(12),
gasCost: gasSwap,
- validateStack: makeSwapStackFunc(13),
+ validateStack: vm.MakeSwapStackFunc(13),
valid: true,
},
SWAP13: {
execute: makeSwap(13),
gasCost: gasSwap,
- validateStack: makeSwapStackFunc(14),
+ validateStack: vm.MakeSwapStackFunc(14),
valid: true,
},
SWAP14: {
execute: makeSwap(14),
gasCost: gasSwap,
- validateStack: makeSwapStackFunc(15),
+ validateStack: vm.MakeSwapStackFunc(15),
valid: true,
},
SWAP15: {
execute: makeSwap(15),
gasCost: gasSwap,
- validateStack: makeSwapStackFunc(16),
+ validateStack: vm.MakeSwapStackFunc(16),
valid: true,
},
SWAP16: {
execute: makeSwap(16),
gasCost: gasSwap,
- validateStack: makeSwapStackFunc(17),
+ validateStack: vm.MakeSwapStackFunc(17),
valid: true,
},
LOG0: {
execute: makeLog(0),
gasCost: makeGasLog(0),
- validateStack: makeStackFunc(2, 0),
+ validateStack: vm.MakeStackFunc(2, 0),
memorySize: memoryLog,
valid: true,
writes: true,
@@ -898,7 +898,7 @@ func newFrontierInstructionSet() [256]operation {
LOG1: {
execute: makeLog(1),
gasCost: makeGasLog(1),
- validateStack: makeStackFunc(3, 0),
+ validateStack: vm.MakeStackFunc(3, 0),
memorySize: memoryLog,
valid: true,
writes: true,
@@ -906,7 +906,7 @@ func newFrontierInstructionSet() [256]operation {
LOG2: {
execute: makeLog(2),
gasCost: makeGasLog(2),
- validateStack: makeStackFunc(4, 0),
+ validateStack: vm.MakeStackFunc(4, 0),
memorySize: memoryLog,
valid: true,
writes: true,
@@ -914,7 +914,7 @@ func newFrontierInstructionSet() [256]operation {
LOG3: {
execute: makeLog(3),
gasCost: makeGasLog(3),
- validateStack: makeStackFunc(5, 0),
+ validateStack: vm.MakeStackFunc(5, 0),
memorySize: memoryLog,
valid: true,
writes: true,
@@ -922,7 +922,7 @@ func newFrontierInstructionSet() [256]operation {
LOG4: {
execute: makeLog(4),
gasCost: makeGasLog(4),
- validateStack: makeStackFunc(6, 0),
+ validateStack: vm.MakeStackFunc(6, 0),
memorySize: memoryLog,
valid: true,
writes: true,
@@ -930,7 +930,7 @@ func newFrontierInstructionSet() [256]operation {
CREATE: {
execute: opCreate,
gasCost: gasCreate,
- validateStack: makeStackFunc(3, 1),
+ validateStack: vm.MakeStackFunc(3, 1),
memorySize: memoryCreate,
valid: true,
writes: true,
@@ -939,7 +939,7 @@ func newFrontierInstructionSet() [256]operation {
CALL: {
execute: opCall,
gasCost: gasCall,
- validateStack: makeStackFunc(7, 1),
+ validateStack: vm.MakeStackFunc(7, 1),
memorySize: memoryCall,
valid: true,
returns: true,
@@ -947,7 +947,7 @@ func newFrontierInstructionSet() [256]operation {
CALLCODE: {
execute: opCallCode,
gasCost: gasCallCode,
- validateStack: makeStackFunc(7, 1),
+ validateStack: vm.MakeStackFunc(7, 1),
memorySize: memoryCall,
valid: true,
returns: true,
@@ -955,7 +955,7 @@ func newFrontierInstructionSet() [256]operation {
RETURN: {
execute: opReturn,
gasCost: gasReturn,
- validateStack: makeStackFunc(2, 0),
+ validateStack: vm.MakeStackFunc(2, 0),
memorySize: memoryReturn,
halts: true,
valid: true,
@@ -963,7 +963,7 @@ func newFrontierInstructionSet() [256]operation {
SELFDESTRUCT: {
execute: opSuicide,
gasCost: gasSuicide,
- validateStack: makeStackFunc(1, 0),
+ validateStack: vm.MakeStackFunc(1, 0),
halts: true,
valid: true,
writes: true,
diff --git a/core/vm/logger.go b/core/vm/evm/logger.go
index fd36c26d5..f51943b14 100644
--- a/core/vm/logger.go
+++ b/core/vm/evm/logger.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package vm
+package evm
import (
"encoding/hex"
@@ -27,6 +27,7 @@ import (
"github.com/dexon-foundation/dexon/common/hexutil"
"github.com/dexon-foundation/dexon/common/math"
"github.com/dexon-foundation/dexon/core/types"
+ "github.com/dexon-foundation/dexon/core/vm"
)
// Storage represents a contract's storage.
@@ -99,8 +100,8 @@ func (s *StructLog) ErrorString() string {
// if you need to retain them beyond the current call.
type Tracer interface {
CaptureStart(from common.Address, to common.Address, call bool, input []byte, gas uint64, value *big.Int) error
- CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error
- CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error
+ CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *Contract, depth int, err error) error
+ CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *Contract, depth int, err error) error
CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error
}
@@ -137,10 +138,10 @@ func (l *StructLogger) CaptureStart(from common.Address, to common.Address, crea
// CaptureState logs a new structured log message and pushes it out to the environment
//
// CaptureState also tracks SSTORE ops to track dirty values.
-func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error {
+func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *Contract, depth int, err error) error {
// check if already accumulated the specified number of logs
if l.cfg.Limit != 0 && l.cfg.Limit <= len(l.logs) {
- return ErrTraceLimitReached
+ return vm.ErrTraceLimitReached
}
// initialise new changed values storage container for this contract
@@ -151,10 +152,10 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui
// capture SSTORE opcodes and determine the changed value and store
// it in the local storage container.
- if op == SSTORE && stack.len() >= 2 {
+ if op == SSTORE && stack.Len() >= 2 {
var (
- value = common.BigToHash(stack.data[stack.len()-2])
- address = common.BigToHash(stack.data[stack.len()-1])
+ value = common.BigToHash(stack.Data[stack.Len()-2])
+ address = common.BigToHash(stack.Data[stack.Len()-1])
)
l.changedValues[contract.Address()][address] = value
}
@@ -167,8 +168,8 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui
// Copy a snapshot of the current stack state to a new buffer
var stck []*big.Int
if !l.cfg.DisableStack {
- stck = make([]*big.Int, len(stack.Data()))
- for i, item := range stack.Data() {
+ stck = make([]*big.Int, len(stack.Data))
+ for i, item := range stack.Data {
stck[i] = new(big.Int).Set(item)
}
}
@@ -186,7 +187,7 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui
// CaptureFault implements the Tracer interface to trace an execution fault
// while running an opcode.
-func (l *StructLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error {
+func (l *StructLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *Contract, depth int, err error) error {
return nil
}
diff --git a/core/vm/logger_json.go b/core/vm/evm/logger_json.go
index 9b7555194..e96e435b3 100644
--- a/core/vm/logger_json.go
+++ b/core/vm/evm/logger_json.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
-package vm
+package evm
import (
"encoding/json"
@@ -24,6 +24,7 @@ import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/common/math"
+ "github.com/dexon-foundation/dexon/core/vm"
)
type JSONLogger struct {
@@ -46,7 +47,7 @@ func (l *JSONLogger) CaptureStart(from common.Address, to common.Address, create
}
// CaptureState outputs state information on the logger.
-func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error {
+func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *Contract, depth int, err error) error {
log := StructLog{
Pc: pc,
Op: op,
@@ -62,13 +63,13 @@ func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint
log.Memory = memory.Data()
}
if !l.cfg.DisableStack {
- log.Stack = stack.Data()
+ log.Stack = stack.Data
}
return l.encoder.Encode(log)
}
// CaptureFault outputs state information on the logger.
-func (l *JSONLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error {
+func (l *JSONLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *Contract, depth int, err error) error {
return nil
}
diff --git a/core/vm/logger_test.go b/core/vm/evm/logger_test.go
index 560893c50..a8e0e9044 100644
--- a/core/vm/logger_test.go
+++ b/core/vm/evm/logger_test.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package vm
+package evm
import (
"math/big"
@@ -22,6 +22,7 @@ import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/core/state"
+ "github.com/dexon-foundation/dexon/core/vm"
"github.com/dexon-foundation/dexon/params"
)
@@ -52,12 +53,12 @@ func TestStoreCapture(t *testing.T) {
var (
env = NewEVM(Context{}, &dummyStatedb{}, params.TestChainConfig, Config{})
logger = NewStructLogger(nil)
- mem = NewMemory()
- stack = newstack()
+ mem = vm.NewMemory()
+ stack = NewStack()
contract = NewContract(&dummyContractRef{}, &dummyContractRef{}, new(big.Int), 0)
)
- stack.push(big.NewInt(1))
- stack.push(big.NewInt(0))
+ stack.Push(big.NewInt(1))
+ stack.Push(big.NewInt(0))
var index common.Hash
logger.CaptureState(env, 0, SSTORE, 0, 0, mem, stack, contract, 0, nil)
if len(logger.changedValues[contract.Address()]) == 0 {
diff --git a/core/vm/evm/memory_table.go b/core/vm/evm/memory_table.go
new file mode 100644
index 000000000..c27e95a4a
--- /dev/null
+++ b/core/vm/evm/memory_table.go
@@ -0,0 +1,98 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+package evm
+
+import (
+ "math/big"
+
+ "github.com/dexon-foundation/dexon/common/math"
+ "github.com/dexon-foundation/dexon/core/vm"
+)
+
+func memorySha3(stack *vm.Stack) *big.Int {
+ return vm.CalcMemSize(stack.Back(0), stack.Back(1))
+}
+
+func memoryCallDataCopy(stack *vm.Stack) *big.Int {
+ return vm.CalcMemSize(stack.Back(0), stack.Back(2))
+}
+
+func memoryReturnDataCopy(stack *vm.Stack) *big.Int {
+ return vm.CalcMemSize(stack.Back(0), stack.Back(2))
+}
+
+func memoryCodeCopy(stack *vm.Stack) *big.Int {
+ return vm.CalcMemSize(stack.Back(0), stack.Back(2))
+}
+
+func memoryExtCodeCopy(stack *vm.Stack) *big.Int {
+ return vm.CalcMemSize(stack.Back(1), stack.Back(3))
+}
+
+func memoryMLoad(stack *vm.Stack) *big.Int {
+ return vm.CalcMemSize(stack.Back(0), big32)
+}
+
+func memoryMStore8(stack *vm.Stack) *big.Int {
+ return vm.CalcMemSize(stack.Back(0), big1)
+}
+
+func memoryMStore(stack *vm.Stack) *big.Int {
+ return vm.CalcMemSize(stack.Back(0), big32)
+}
+
+func memoryCreate(stack *vm.Stack) *big.Int {
+ return vm.CalcMemSize(stack.Back(1), stack.Back(2))
+}
+
+func memoryCreate2(stack *vm.Stack) *big.Int {
+ return vm.CalcMemSize(stack.Back(1), stack.Back(2))
+}
+
+func memoryCall(stack *vm.Stack) *big.Int {
+ x := vm.CalcMemSize(stack.Back(5), stack.Back(6))
+ y := vm.CalcMemSize(stack.Back(3), stack.Back(4))
+
+ return math.BigMax(x, y)
+}
+
+func memoryDelegateCall(stack *vm.Stack) *big.Int {
+ x := vm.CalcMemSize(stack.Back(4), stack.Back(5))
+ y := vm.CalcMemSize(stack.Back(2), stack.Back(3))
+
+ return math.BigMax(x, y)
+}
+
+func memoryStaticCall(stack *vm.Stack) *big.Int {
+ x := vm.CalcMemSize(stack.Back(4), stack.Back(5))
+ y := vm.CalcMemSize(stack.Back(2), stack.Back(3))
+
+ return math.BigMax(x, y)
+}
+
+func memoryReturn(stack *vm.Stack) *big.Int {
+ return vm.CalcMemSize(stack.Back(0), stack.Back(1))
+}
+
+func memoryRevert(stack *vm.Stack) *big.Int {
+ return vm.CalcMemSize(stack.Back(0), stack.Back(1))
+}
+
+func memoryLog(stack *vm.Stack) *big.Int {
+ mSize, mStart := stack.Back(1), stack.Back(0)
+ return vm.CalcMemSize(mStart, mSize)
+}
diff --git a/core/vm/opcodes.go b/core/vm/evm/opcodes.go
index 8762d4b43..22ff00c7d 100644
--- a/core/vm/opcodes.go
+++ b/core/vm/evm/opcodes.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package vm
+package evm
import (
"fmt"
diff --git a/core/vm/runtime/doc.go b/core/vm/evm/runtime/doc.go
index a3b464a7d..a3b464a7d 100644
--- a/core/vm/runtime/doc.go
+++ b/core/vm/evm/runtime/doc.go
diff --git a/core/vm/runtime/env.go b/core/vm/evm/runtime/env.go
index 6f241a329..c46580140 100644
--- a/core/vm/runtime/env.go
+++ b/core/vm/evm/runtime/env.go
@@ -19,7 +19,7 @@ package runtime
import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/core"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
)
func NewEnv(cfg *Config) *vm.EVM {
diff --git a/core/vm/runtime/fuzz.go b/core/vm/evm/runtime/fuzz.go
index cb9ff08b5..cb9ff08b5 100644
--- a/core/vm/runtime/fuzz.go
+++ b/core/vm/evm/runtime/fuzz.go
diff --git a/core/vm/runtime/runtime.go b/core/vm/evm/runtime/runtime.go
index 5656f661a..93e6322f4 100644
--- a/core/vm/runtime/runtime.go
+++ b/core/vm/evm/runtime/runtime.go
@@ -23,7 +23,7 @@ import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/core/state"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/params"
diff --git a/core/vm/runtime/runtime_example_test.go b/core/vm/evm/runtime/runtime_example_test.go
index 036cfe558..c6050a771 100644
--- a/core/vm/runtime/runtime_example_test.go
+++ b/core/vm/evm/runtime/runtime_example_test.go
@@ -20,7 +20,7 @@ import (
"fmt"
"github.com/dexon-foundation/dexon/common"
- "github.com/dexon-foundation/dexon/core/vm/runtime"
+ "github.com/dexon-foundation/dexon/core/vm/evm/runtime"
)
func ExampleExecute() {
diff --git a/core/vm/runtime/runtime_test.go b/core/vm/evm/runtime/runtime_test.go
index fe03bd43f..43b8da325 100644
--- a/core/vm/runtime/runtime_test.go
+++ b/core/vm/evm/runtime/runtime_test.go
@@ -24,7 +24,7 @@ import (
"github.com/dexon-foundation/dexon/accounts/abi"
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/core/state"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/params"
)
diff --git a/core/vm/evm/stack.go b/core/vm/evm/stack.go
new file mode 100644
index 000000000..4545201ce
--- /dev/null
+++ b/core/vm/evm/stack.go
@@ -0,0 +1,24 @@
+package evm
+
+import (
+ "math/big"
+ "sync"
+
+ "github.com/dexon-foundation/dexon/core/vm"
+)
+
+var stackPool = sync.Pool{
+ New: func() interface{} {
+ return &vm.Stack{Data: make([]*big.Int, 0, 1024)}
+ },
+}
+
+func NewStack() *vm.Stack {
+ stack := stackPool.Get().(*vm.Stack)
+ stack.Data = stack.Data[:0]
+ return stack
+}
+
+func Recyclestack(stack *vm.Stack) {
+ stackPool.Put(stack)
+}
diff --git a/core/vm/int_pool_verifier.go b/core/vm/int_pool_verifier.go
index 82fbfed69..c03408b5f 100644
--- a/core/vm/int_pool_verifier.go
+++ b/core/vm/int_pool_verifier.go
@@ -20,9 +20,9 @@ package vm
import "fmt"
-const verifyPool = true
+const VerifyPool = true
-func verifyIntegerPool(ip *intPool) {
+func VerifyIntegerPool(ip *IntPool) {
for i, item := range ip.pool.data {
if item.Cmp(checkVal) != 0 {
panic(fmt.Sprintf("%d'th item failed aggressive pool check. Value was modified", i))
diff --git a/core/vm/int_pool_verifier_empty.go b/core/vm/int_pool_verifier_empty.go
index a5f1dc02b..66d99f16f 100644
--- a/core/vm/int_pool_verifier_empty.go
+++ b/core/vm/int_pool_verifier_empty.go
@@ -18,6 +18,6 @@
package vm
-const verifyPool = false
+const VerifyPool = false
-func verifyIntegerPool(ip *intPool) {}
+func VerifyIntegerPool(ip *IntPool) {}
diff --git a/core/vm/intpool.go b/core/vm/intpool.go
index 917a78d56..9e73b8b71 100644
--- a/core/vm/intpool.go
+++ b/core/vm/intpool.go
@@ -23,84 +23,84 @@ import (
var checkVal = big.NewInt(-42)
-const poolLimit = 256
+const PoolLimit = 256
-// intPool is a pool of big integers that
+// IntPool is a Pool of big integers that
// can be reused for all big.Int operations.
-type intPool struct {
- pool *Stack
+type IntPool struct {
+ Pool *Stack
}
-func newIntPool() *intPool {
- return &intPool{pool: newstack()}
+func newIntPool() *IntPool {
+ return &IntPool{Pool: &Stack{Data: make([]*big.Int, 0, 1024)}}
}
-// get retrieves a big int from the pool, allocating one if the pool is empty.
+// get retrieves a big int from the Pool, allocating one if the Pool is empty.
// Note, the returned int's value is arbitrary and will not be zeroed!
-func (p *intPool) get() *big.Int {
- if p.pool.len() > 0 {
- return p.pool.pop()
+func (p *IntPool) Get() *big.Int {
+ if p.Pool.Len() > 0 {
+ return p.Pool.Pop()
}
return new(big.Int)
}
-// getZero retrieves a big int from the pool, setting it to zero or allocating
-// a new one if the pool is empty.
-func (p *intPool) getZero() *big.Int {
- if p.pool.len() > 0 {
- return p.pool.pop().SetUint64(0)
+// getZero retrieves a big int from the Pool, setting it to zero or allocating
+// a new one if the Pool is empty.
+func (p *IntPool) GetZero() *big.Int {
+ if p.Pool.Len() > 0 {
+ return p.Pool.Pop().SetUint64(0)
}
return new(big.Int)
}
-// put returns an allocated big int to the pool to be later reused by get calls.
+// put returns an allocated big int to the Pool to be later reused by get calls.
// Note, the values as saved as is; neither put nor get zeroes the ints out!
-func (p *intPool) put(is ...*big.Int) {
- if len(p.pool.data) > poolLimit {
+func (p *IntPool) Put(is ...*big.Int) {
+ if len(p.Pool.Data) > PoolLimit {
return
}
for _, i := range is {
// verifyPool is a build flag. Pool verification makes sure the integrity
- // of the integer pool by comparing values to a default value.
- if verifyPool {
+ // of the integer Pool by comparing values to a default value.
+ if VerifyPool {
i.Set(checkVal)
}
- p.pool.push(i)
+ p.Pool.Push(i)
}
}
-// The intPool pool's default capacity
-const poolDefaultCap = 25
+// The IntPool Pool's default capacity
+const PoolDefaultCap = 25
-// intPoolPool manages a pool of intPools.
-type intPoolPool struct {
- pools []*intPool
+// IntPoolPool manages a Pool of IntPools.
+type IntPoolPool struct {
+ Pools []*IntPool
lock sync.Mutex
}
-var poolOfIntPools = &intPoolPool{
- pools: make([]*intPool, 0, poolDefaultCap),
+var PoolOfIntPools = &IntPoolPool{
+ Pools: make([]*IntPool, 0, PoolDefaultCap),
}
-// get is looking for an available pool to return.
-func (ipp *intPoolPool) get() *intPool {
+// get is looking for an available Pool to return.
+func (ipp *IntPoolPool) Get() *IntPool {
ipp.lock.Lock()
defer ipp.lock.Unlock()
- if len(poolOfIntPools.pools) > 0 {
- ip := ipp.pools[len(ipp.pools)-1]
- ipp.pools = ipp.pools[:len(ipp.pools)-1]
+ if len(PoolOfIntPools.Pools) > 0 {
+ ip := ipp.Pools[len(ipp.Pools)-1]
+ ipp.Pools = ipp.Pools[:len(ipp.Pools)-1]
return ip
}
return newIntPool()
}
-// put a pool that has been allocated with get.
-func (ipp *intPoolPool) put(ip *intPool) {
+// put a Pool that has been allocated with get.
+func (ipp *IntPoolPool) Put(ip *IntPool) {
ipp.lock.Lock()
defer ipp.lock.Unlock()
- if len(ipp.pools) < cap(ipp.pools) {
- ipp.pools = append(ipp.pools, ip)
+ if len(ipp.Pools) < cap(ipp.Pools) {
+ ipp.Pools = append(ipp.Pools, ip)
}
}
diff --git a/core/vm/intpool_test.go b/core/vm/intpool_test.go
index 6c0d00f3c..120d9a682 100644
--- a/core/vm/intpool_test.go
+++ b/core/vm/intpool_test.go
@@ -21,35 +21,35 @@ import (
)
func TestIntPoolPoolGet(t *testing.T) {
- poolOfIntPools.pools = make([]*intPool, 0, poolDefaultCap)
+ PoolOfIntPools.Pools = make([]*IntPool, 0, PoolDefaultCap)
- nip := poolOfIntPools.get()
+ nip := PoolOfIntPools.Get()
if nip == nil {
t.Fatalf("Invalid pool allocation")
}
}
func TestIntPoolPoolPut(t *testing.T) {
- poolOfIntPools.pools = make([]*intPool, 0, poolDefaultCap)
+ PoolOfIntPools.Pools = make([]*IntPool, 0, PoolDefaultCap)
- nip := poolOfIntPools.get()
- if len(poolOfIntPools.pools) != 0 {
+ nip := PoolOfIntPools.Get()
+ if len(PoolOfIntPools.Pools) != 0 {
t.Fatalf("Pool got added to list when none should have been")
}
- poolOfIntPools.put(nip)
- if len(poolOfIntPools.pools) == 0 {
+ PoolOfIntPools.Put(nip)
+ if len(PoolOfIntPools.Pools) == 0 {
t.Fatalf("Pool did not get added to list when one should have been")
}
}
func TestIntPoolPoolReUse(t *testing.T) {
- poolOfIntPools.pools = make([]*intPool, 0, poolDefaultCap)
- nip := poolOfIntPools.get()
- poolOfIntPools.put(nip)
- poolOfIntPools.get()
+ PoolOfIntPools.Pools = make([]*IntPool, 0, PoolDefaultCap)
+ nip := PoolOfIntPools.Get()
+ PoolOfIntPools.Put(nip)
+ PoolOfIntPools.Get()
- if len(poolOfIntPools.pools) != 0 {
- t.Fatalf("Invalid number of pools. Got %d, expected %d", len(poolOfIntPools.pools), 0)
+ if len(PoolOfIntPools.Pools) != 0 {
+ t.Fatalf("Invalid number of pools. Got %d, expected %d", len(PoolOfIntPools.Pools), 0)
}
}
diff --git a/core/vm/memory.go b/core/vm/memory.go
index 65ffe26c7..bbfa4cc2a 100644
--- a/core/vm/memory.go
+++ b/core/vm/memory.go
@@ -25,8 +25,8 @@ import (
// Memory implements a simple memory model for the ethereum virtual machine.
type Memory struct {
- store []byte
- lastGasCost uint64
+ Store []byte
+ LastGasCost uint64
}
// NewMemory returns a new memory model.
@@ -39,33 +39,33 @@ func (m *Memory) Set(offset, size uint64, value []byte) {
// It's possible the offset is greater than 0 and size equals 0. This is because
// the calcMemSize (common.go) could potentially return 0 when size is zero (NO-OP)
if size > 0 {
- // length of store may never be less than offset + size.
- // The store should be resized PRIOR to setting the memory
- if offset+size > uint64(len(m.store)) {
- panic("invalid memory: store empty")
+ // length of.Store may never be less than offset + size.
+ // The.Store should be resized PRIOR to setting the memory
+ if offset+size > uint64(len(m.Store)) {
+ panic("invalid memory:.Store empty")
}
- copy(m.store[offset:offset+size], value)
+ copy(m.Store[offset:offset+size], value)
}
}
// Set32 sets the 32 bytes starting at offset to the value of val, left-padded with zeroes to
// 32 bytes.
func (m *Memory) Set32(offset uint64, val *big.Int) {
- // length of store may never be less than offset + size.
- // The store should be resized PRIOR to setting the memory
- if offset+32 > uint64(len(m.store)) {
- panic("invalid memory: store empty")
+ // length of.Store may never be less than offset + size.
+ // The.Store should be resized PRIOR to setting the memory
+ if offset+32 > uint64(len(m.Store)) {
+ panic("invalid memory:.Store empty")
}
// Zero the memory area
- copy(m.store[offset:offset+32], []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})
+ copy(m.Store[offset:offset+32], []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})
// Fill in relevant bits
- math.ReadBits(val, m.store[offset:offset+32])
+ math.ReadBits(val, m.Store[offset:offset+32])
}
// Resize resizes the memory to size
func (m *Memory) Resize(size uint64) {
if uint64(m.Len()) < size {
- m.store = append(m.store, make([]byte, size-uint64(m.Len()))...)
+ m.Store = append(m.Store, make([]byte, size-uint64(m.Len()))...)
}
}
@@ -75,9 +75,9 @@ func (m *Memory) Get(offset, size int64) (cpy []byte) {
return nil
}
- if len(m.store) > int(offset) {
+ if len(m.Store) > int(offset) {
cpy = make([]byte, size)
- copy(cpy, m.store[offset:offset+size])
+ copy(cpy, m.Store[offset:offset+size])
return
}
@@ -91,8 +91,8 @@ func (m *Memory) GetPtr(offset, size int64) []byte {
return nil
}
- if len(m.store) > int(offset) {
- return m.store[offset : offset+size]
+ if len(m.Store) > int(offset) {
+ return m.Store[offset : offset+size]
}
return nil
@@ -100,21 +100,21 @@ func (m *Memory) GetPtr(offset, size int64) []byte {
// Len returns the length of the backing slice
func (m *Memory) Len() int {
- return len(m.store)
+ return len(m.Store)
}
// Data returns the backing slice
func (m *Memory) Data() []byte {
- return m.store
+ return m.Store
}
// Print dumps the content of the memory.
func (m *Memory) Print() {
- fmt.Printf("### mem %d bytes ###\n", len(m.store))
- if len(m.store) > 0 {
+ fmt.Printf("### mem %d bytes ###\n", len(m.Store))
+ if len(m.Store) > 0 {
addr := 0
- for i := 0; i+32 <= len(m.store); i += 32 {
- fmt.Printf("%03d: % x\n", addr, m.store[i:i+32])
+ for i := 0; i+32 <= len(m.Store); i += 32 {
+ fmt.Printf("%03d: % x\n", addr, m.Store[i:i+32])
addr++
}
} else {
diff --git a/core/vm/memory_table.go b/core/vm/memory_table.go
deleted file mode 100644
index 13f15b943..000000000
--- a/core/vm/memory_table.go
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2017 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-
-package vm
-
-import (
- "math/big"
-
- "github.com/dexon-foundation/dexon/common/math"
-)
-
-func memorySha3(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), stack.Back(1))
-}
-
-func memoryCallDataCopy(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), stack.Back(2))
-}
-
-func memoryReturnDataCopy(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), stack.Back(2))
-}
-
-func memoryCodeCopy(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), stack.Back(2))
-}
-
-func memoryExtCodeCopy(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(1), stack.Back(3))
-}
-
-func memoryMLoad(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), big32)
-}
-
-func memoryMStore8(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), big1)
-}
-
-func memoryMStore(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), big32)
-}
-
-func memoryCreate(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(1), stack.Back(2))
-}
-
-func memoryCreate2(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(1), stack.Back(2))
-}
-
-func memoryCall(stack *Stack) *big.Int {
- x := calcMemSize(stack.Back(5), stack.Back(6))
- y := calcMemSize(stack.Back(3), stack.Back(4))
-
- return math.BigMax(x, y)
-}
-
-func memoryDelegateCall(stack *Stack) *big.Int {
- x := calcMemSize(stack.Back(4), stack.Back(5))
- y := calcMemSize(stack.Back(2), stack.Back(3))
-
- return math.BigMax(x, y)
-}
-
-func memoryStaticCall(stack *Stack) *big.Int {
- x := calcMemSize(stack.Back(4), stack.Back(5))
- y := calcMemSize(stack.Back(2), stack.Back(3))
-
- return math.BigMax(x, y)
-}
-
-func memoryReturn(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), stack.Back(1))
-}
-
-func memoryRevert(stack *Stack) *big.Int {
- return calcMemSize(stack.Back(0), stack.Back(1))
-}
-
-func memoryLog(stack *Stack) *big.Int {
- mSize, mStart := stack.Back(1), stack.Back(0)
- return calcMemSize(mStart, mSize)
-}
diff --git a/core/vm/oracle_contracts.go b/core/vm/oracle_contracts.go
index 3a84015b5..4a3c05ccf 100644
--- a/core/vm/oracle_contracts.go
+++ b/core/vm/oracle_contracts.go
@@ -1921,7 +1921,7 @@ func (g *GovernanceContract) payFine(nodeAddr common.Address) ([]byte, error) {
g.state.UpdateNode(nodeOffset, node)
// Pay the fine to governance owner.
- g.evm.StateDB.AddBalance(g.state.Owner(), g.contract.Value())
+ g.evm.StateDB.AddBalance(g.state.Owner(), g.contract.Value)
g.state.emitFinePaid(nodeAddr, g.contract.Value())
diff --git a/core/vm/stack.go b/core/vm/stack.go
index 14b1c289b..45553d499 100644
--- a/core/vm/stack.go
+++ b/core/vm/stack.go
@@ -13,83 +13,60 @@
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-
package vm
import (
"fmt"
"math/big"
- "sync"
)
-var stackPool = sync.Pool{
- New: func() interface{} {
- return &Stack{data: make([]*big.Int, 0, 1024)}
- },
-}
-
// Stack is an object for basic stack operations. Items popped to the stack are
// expected to be changed and modified. stack does not take care of adding newly
// initialised objects.
type Stack struct {
- data []*big.Int
-}
-
-func newstack() *Stack {
- stack := stackPool.Get().(*Stack)
- stack.data = stack.data[:0]
- return stack
-}
-
-func recyclestack(stack *Stack) {
- stackPool.Put(stack)
-}
-
-// Data returns the underlying big.Int array.
-func (st *Stack) Data() []*big.Int {
- return st.data
+ Data []*big.Int
}
-func (st *Stack) push(d *big.Int) {
+func (st *Stack) Push(d *big.Int) {
// NOTE push limit (1024) is checked in baseCheck
//stackItem := new(big.Int).Set(d)
- //st.data = append(st.data, stackItem)
- st.data = append(st.data, d)
+ //st.Data = append(st.Data, stackItem)
+ st.Data = append(st.Data, d)
}
-func (st *Stack) pushN(ds ...*big.Int) {
- st.data = append(st.data, ds...)
+func (st *Stack) PushN(ds ...*big.Int) {
+ st.Data = append(st.Data, ds...)
}
-func (st *Stack) pop() (ret *big.Int) {
- ret = st.data[len(st.data)-1]
- st.data = st.data[:len(st.data)-1]
+func (st *Stack) Pop() (ret *big.Int) {
+ ret = st.Data[len(st.Data)-1]
+ st.Data = st.Data[:len(st.Data)-1]
return
}
-func (st *Stack) len() int {
- return len(st.data)
+func (st *Stack) Len() int {
+ return len(st.Data)
}
-func (st *Stack) swap(n int) {
- st.data[st.len()-n], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-n]
+func (st *Stack) Swap(n int) {
+ st.Data[st.Len()-n], st.Data[st.Len()-1] = st.Data[st.Len()-1], st.Data[st.Len()-n]
}
-func (st *Stack) dup(pool *intPool, n int) {
- st.push(pool.get().Set(st.data[st.len()-n]))
+func (st *Stack) Dup(pool *IntPool, n int) {
+ st.Push(pool.Get().Set(st.Data[st.Len()-n]))
}
-func (st *Stack) peek() *big.Int {
- return st.data[st.len()-1]
+func (st *Stack) Peek() *big.Int {
+ return st.Data[st.Len()-1]
}
// Back returns the n'th item in stack
func (st *Stack) Back(n int) *big.Int {
- return st.data[st.len()-n-1]
+ return st.Data[st.Len()-n-1]
}
-func (st *Stack) require(n int) error {
- if st.len() < n {
- return fmt.Errorf("stack underflow (%d <=> %d)", len(st.data), n)
+func (st *Stack) Require(n int) error {
+ if st.Len() < n {
+ return fmt.Errorf("stack underflow (%d <=> %d)", len(st.Data), n)
}
return nil
}
@@ -97,8 +74,8 @@ func (st *Stack) require(n int) error {
// Print dumps the content of the stack
func (st *Stack) Print() {
fmt.Println("### stack ###")
- if len(st.data) > 0 {
- for i, val := range st.data {
+ if len(st.Data) > 0 {
+ for i, val := range st.Data {
fmt.Printf("%-3d %v\n", i, val)
}
} else {
diff --git a/core/vm/stack_table.go b/core/vm/stack_table.go
index df544aef8..187d8fa1f 100644
--- a/core/vm/stack_table.go
+++ b/core/vm/stack_table.go
@@ -22,23 +22,27 @@ import (
"github.com/dexon-foundation/dexon/params"
)
-func makeStackFunc(pop, push int) stackValidationFunc {
+type (
+ StackValidationFunc func(*Stack) error
+)
+
+func MakeStackFunc(pop, push int) StackValidationFunc {
return func(stack *Stack) error {
- if err := stack.require(pop); err != nil {
+ if err := stack.Require(pop); err != nil {
return err
}
- if stack.len()+push-pop > int(params.StackLimit) {
- return fmt.Errorf("stack limit reached %d (%d)", stack.len(), params.StackLimit)
+ if stack.Len()+push-pop > int(params.StackLimit) {
+ return fmt.Errorf("stack limit reached %d (%d)", stack.Len(), params.StackLimit)
}
return nil
}
}
-func makeDupStackFunc(n int) stackValidationFunc {
- return makeStackFunc(n, n+1)
+func MakeDupStackFunc(n int) StackValidationFunc {
+ return MakeStackFunc(n, n+1)
}
-func makeSwapStackFunc(n int) stackValidationFunc {
- return makeStackFunc(n, n)
+func MakeSwapStackFunc(n int) StackValidationFunc {
+ return MakeStackFunc(n, n)
}
diff --git a/dex/api_backend.go b/dex/api_backend.go
index 7333a9bb1..7bb5581ee 100644
--- a/dex/api_backend.go
+++ b/dex/api_backend.go
@@ -27,7 +27,7 @@ import (
"github.com/dexon-foundation/dexon/core/bloombits"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/eth/gasprice"
"github.com/dexon-foundation/dexon/internal/ethapi"
diff --git a/dex/api_tracer.go b/dex/api_tracer.go
index d451c376d..0db75e25c 100644
--- a/dex/api_tracer.go
+++ b/dex/api_tracer.go
@@ -34,7 +34,7 @@ import (
"github.com/dexon-foundation/dexon/core/rawdb"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/eth/tracers"
"github.com/dexon-foundation/dexon/internal/ethapi"
"github.com/dexon-foundation/dexon/log"
@@ -64,7 +64,7 @@ type TraceConfig struct {
// StdTraceConfig holds extra parameters to standard-json trace functions.
type StdTraceConfig struct {
- *vm.LogConfig
+ *evm.LogConfig
Reexec *uint64
TxHash common.Hash
}
@@ -546,7 +546,7 @@ func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block
}
// Retrieve the tracing configurations, or use default values
var (
- logConfig vm.LogConfig
+ logConfig evm.LogConfig
txHash common.Hash
)
if config != nil {
@@ -568,7 +568,7 @@ func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block
msg, _ = tx.AsMessage(signer)
vmctx = core.NewEVMContext(msg, block.Header(), api.dex.blockchain, nil)
- vmConf vm.Config
+ vmConf evm.Config
dump *os.File
err error
)
@@ -584,14 +584,14 @@ func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block
dumps = append(dumps, dump.Name())
// Swap out the noop logger to the standard tracer
- vmConf = vm.Config{
+ vmConf = evm.Config{
Debug: true,
- Tracer: vm.NewJSONLogger(&logConfig, bufio.NewWriter(dump)),
+ Tracer: evm.NewJSONLogger(&logConfig, bufio.NewWriter(dump)),
EnablePreimageRecording: true,
}
}
// Execute the transaction and flush any traces to disk
- vmenv := vm.NewEVM(vmctx, statedb, api.config, vmConf)
+ vmenv := evm.NewEVM(vmctx, statedb, api.config, vmConf)
_, _, _, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()))
if dump != nil {
diff --git a/dex/backend.go b/dex/backend.go
index 26a0b49eb..8344c7973 100644
--- a/dex/backend.go
+++ b/dex/backend.go
@@ -28,7 +28,7 @@ import (
"github.com/dexon-foundation/dexon/core"
"github.com/dexon-foundation/dexon/core/bloombits"
"github.com/dexon-foundation/dexon/core/rawdb"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/dex/downloader"
"github.com/dexon-foundation/dexon/eth/filters"
"github.com/dexon-foundation/dexon/eth/gasprice"
diff --git a/dex/downloader/downloader.go b/dex/downloader/downloader.go
index 0847cd062..6ef83b7cb 100644
--- a/dex/downloader/downloader.go
+++ b/dex/downloader/downloader.go
@@ -31,7 +31,7 @@ import (
"github.com/dexon-foundation/dexon/core/rawdb"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/event"
diff --git a/dex/downloader/downloader_test.go b/dex/downloader/downloader_test.go
index e01e0d96b..3258d069e 100644
--- a/dex/downloader/downloader_test.go
+++ b/dex/downloader/downloader_test.go
@@ -33,7 +33,7 @@ import (
"github.com/dexon-foundation/dexon/consensus/dexcon"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/event"
"github.com/dexon-foundation/dexon/rlp"
diff --git a/dex/downloader/testchain_test.go b/dex/downloader/testchain_test.go
index e5c5e4d23..61778c028 100644
--- a/dex/downloader/testchain_test.go
+++ b/dex/downloader/testchain_test.go
@@ -29,7 +29,7 @@ import (
"github.com/dexon-foundation/dexon/core"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/params"
diff --git a/dex/governance.go b/dex/governance.go
index ec09969b0..6908fd0d9 100644
--- a/dex/governance.go
+++ b/dex/governance.go
@@ -28,7 +28,7 @@ import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/core"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/log"
"github.com/dexon-foundation/dexon/params"
diff --git a/dex/helper_test.go b/dex/helper_test.go
index 1d267d9ae..4d6330108 100644
--- a/dex/helper_test.go
+++ b/dex/helper_test.go
@@ -31,7 +31,7 @@ import (
"github.com/dexon-foundation/dexon/consensus/ethash"
"github.com/dexon-foundation/dexon/core"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/dex/downloader"
"github.com/dexon-foundation/dexon/ethdb"
diff --git a/eth/api_backend.go b/eth/api_backend.go
index 696b6c64a..e50f62814 100644
--- a/eth/api_backend.go
+++ b/eth/api_backend.go
@@ -27,7 +27,7 @@ import (
"github.com/dexon-foundation/dexon/core/bloombits"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/eth/gasprice"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/event"
diff --git a/eth/api_tracer.go b/eth/api_tracer.go
index c80cb9a5c..c3523b8bc 100644
--- a/eth/api_tracer.go
+++ b/eth/api_tracer.go
@@ -34,7 +34,7 @@ import (
"github.com/dexon-foundation/dexon/core/rawdb"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/eth/tracers"
"github.com/dexon-foundation/dexon/internal/ethapi"
"github.com/dexon-foundation/dexon/log"
diff --git a/eth/backend.go b/eth/backend.go
index f75f2e521..815049251 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -35,7 +35,7 @@ import (
"github.com/dexon-foundation/dexon/core/bloombits"
"github.com/dexon-foundation/dexon/core/rawdb"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/eth/downloader"
"github.com/dexon-foundation/dexon/eth/filters"
"github.com/dexon-foundation/dexon/eth/gasprice"
diff --git a/eth/handler_test.go b/eth/handler_test.go
index a9fdaa87f..4041fbe59 100644
--- a/eth/handler_test.go
+++ b/eth/handler_test.go
@@ -29,7 +29,7 @@ import (
"github.com/dexon-foundation/dexon/core"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/eth/downloader"
"github.com/dexon-foundation/dexon/ethdb"
diff --git a/eth/helper_test.go b/eth/helper_test.go
index 9a30afef3..7b2de4574 100644
--- a/eth/helper_test.go
+++ b/eth/helper_test.go
@@ -31,7 +31,7 @@ import (
"github.com/dexon-foundation/dexon/consensus/ethash"
"github.com/dexon-foundation/dexon/core"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/eth/downloader"
"github.com/dexon-foundation/dexon/ethdb"
diff --git a/eth/tracers/tracer.go b/eth/tracers/tracer.go
index 21c2b72d2..f232df49e 100644
--- a/eth/tracers/tracer.go
+++ b/eth/tracers/tracer.go
@@ -28,6 +28,7 @@ import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/common/hexutil"
"github.com/dexon-foundation/dexon/core/vm"
+ "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/log"
duktape "gopkg.in/olebedev/go-duktape.v3"
@@ -68,7 +69,7 @@ func pushBigInt(n *big.Int, ctx *duktape.Context) {
// opWrapper provides a JavaScript wrapper around OpCode.
type opWrapper struct {
- op vm.OpCode
+ op evm.OpCode
}
// pushObject assembles a JSVM object wrapping a swappable opcode and pushes it
@@ -140,20 +141,20 @@ func (mw *memoryWrapper) pushObject(vm *duktape.Context) {
vm.PutPropString(obj, "getUint")
}
-// stackWrapper provides a JavaScript wrapper around vm.Stack.
+// stackWrapper provides a JavaScript wrapper around evm.Stack.
type stackWrapper struct {
stack *vm.Stack
}
// peek returns the nth-from-the-top element of the stack.
func (sw *stackWrapper) peek(idx int) *big.Int {
- if len(sw.stack.Data()) <= idx {
+ if len(sw.stack.Data) <= idx {
// TODO(karalabe): We can't js-throw from Go inside duktape inside Go. The Go
// runtime goes belly up https://github.com/golang/go/issues/15639.
- log.Warn("Tracer accessed out of bound stack", "size", len(sw.stack.Data()), "index", idx)
+ log.Warn("Tracer accessed out of bound stack", "size", len(sw.stack.Data), "index", idx)
return new(big.Int)
}
- return sw.stack.Data()[len(sw.stack.Data())-idx-1]
+ return sw.stack.Data[len(sw.stack.Data)-idx-1]
}
// pushObject assembles a JSVM object wrapping a swappable stack and pushes it
@@ -161,7 +162,7 @@ func (sw *stackWrapper) peek(idx int) *big.Int {
func (sw *stackWrapper) pushObject(vm *duktape.Context) {
obj := vm.PushObject()
- vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushInt(len(sw.stack.Data())); return 1 })
+ vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushInt(len(sw.stack.Data)); return 1 })
vm.PutPropString(obj, "length")
// Generate the `peek` method which takes an int and returns a bigint
@@ -175,9 +176,9 @@ func (sw *stackWrapper) pushObject(vm *duktape.Context) {
vm.PutPropString(obj, "peek")
}
-// dbWrapper provides a JavaScript wrapper around vm.Database.
+// dbWrapper provides a JavaScript wrapper around evm.Database.
type dbWrapper struct {
- db vm.StateDB
+ db evm.StateDB
}
// pushObject assembles a JSVM object wrapping a swappable database and pushes it
@@ -230,9 +231,9 @@ func (dw *dbWrapper) pushObject(vm *duktape.Context) {
vm.PutPropString(obj, "exists")
}
-// contractWrapper provides a JavaScript wrapper around vm.Contract
+// contractWrapper provides a JavaScript wrapper around evm.Contract
type contractWrapper struct {
- contract *vm.Contract
+ contract *evm.Contract
}
// pushObject assembles a JSVM object wrapping a swappable contract and pushes it
@@ -390,7 +391,7 @@ func New(code string) (*Tracer, error) {
return 1
})
tracer.vm.PushGlobalGoFunction("isPrecompiled", func(ctx *duktape.Context) int {
- _, ok := vm.PrecompiledContractsByzantium[common.BytesToAddress(popSlice(ctx))]
+ _, ok := evm.PrecompiledContractsByzantium[common.BytesToAddress(popSlice(ctx))]
ctx.PushBoolean(ok)
return 1
})
@@ -532,7 +533,7 @@ func (jst *Tracer) CaptureStart(from common.Address, to common.Address, create b
}
// CaptureState implements the Tracer interface to trace a single step of VM execution.
-func (jst *Tracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) error {
+func (jst *Tracer) CaptureState(env *evm.EVM, pc uint64, op evm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *evm.Contract, depth int, err error) error {
if jst.err == nil {
// Initialize the context if it wasn't done yet
if !jst.inited {
@@ -571,7 +572,7 @@ func (jst *Tracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost
// CaptureFault implements the Tracer interface to trace an execution fault
// while running an opcode.
-func (jst *Tracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) error {
+func (jst *Tracer) CaptureFault(env *evm.EVM, pc uint64, op evm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *evm.Contract, depth int, err error) error {
if jst.err == nil {
// Apart from the error, everything matches the previous invocation
jst.errorValue = new(string)
diff --git a/eth/tracers/tracer_test.go b/eth/tracers/tracer_test.go
index 75140a5db..eacc9a591 100644
--- a/eth/tracers/tracer_test.go
+++ b/eth/tracers/tracer_test.go
@@ -26,7 +26,7 @@ import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/core/state"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/params"
)
diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go
index 1436cc67f..0b8f75ab3 100644
--- a/eth/tracers/tracers_test.go
+++ b/eth/tracers/tracers_test.go
@@ -32,7 +32,7 @@ import (
"github.com/dexon-foundation/dexon/common/math"
"github.com/dexon-foundation/dexon/core"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/params"
diff --git a/indexer/blockchain.go b/indexer/blockchain.go
index 390a5fa64..996bc891c 100644
--- a/indexer/blockchain.go
+++ b/indexer/blockchain.go
@@ -8,7 +8,7 @@ import (
"github.com/dexon-foundation/dexon/core"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/event"
"github.com/dexon-foundation/dexon/params"
"github.com/dexon-foundation/dexon/rlp"
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
index 1be3bb413..ccc383baf 100644
--- a/internal/ethapi/api.go
+++ b/internal/ethapi/api.go
@@ -35,7 +35,7 @@ import (
"github.com/dexon-foundation/dexon/core"
"github.com/dexon-foundation/dexon/core/rawdb"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/log"
"github.com/dexon-foundation/dexon/p2p"
diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go
index da13d3661..256da5dde 100644
--- a/internal/ethapi/backend.go
+++ b/internal/ethapi/backend.go
@@ -27,7 +27,7 @@ import (
"github.com/dexon-foundation/dexon/core"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/event"
"github.com/dexon-foundation/dexon/params"
diff --git a/les/api_backend.go b/les/api_backend.go
index f69e67c60..2ca62c8a4 100644
--- a/les/api_backend.go
+++ b/les/api_backend.go
@@ -28,7 +28,7 @@ import (
"github.com/dexon-foundation/dexon/core/rawdb"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/eth/gasprice"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/event"
diff --git a/les/helper_test.go b/les/helper_test.go
index 2ce78f0c9..550fb1905 100644
--- a/les/helper_test.go
+++ b/les/helper_test.go
@@ -30,7 +30,7 @@ import (
"github.com/dexon-foundation/dexon/consensus/ethash"
"github.com/dexon-foundation/dexon/core"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/eth"
"github.com/dexon-foundation/dexon/ethdb"
diff --git a/les/odr_test.go b/les/odr_test.go
index 9a6b1ef88..f6e6e873b 100644
--- a/les/odr_test.go
+++ b/les/odr_test.go
@@ -29,7 +29,7 @@ import (
"github.com/dexon-foundation/dexon/core/rawdb"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/light"
"github.com/dexon-foundation/dexon/params"
diff --git a/light/odr_test.go b/light/odr_test.go
index 34e1f6f7c..08d4bce32 100644
--- a/light/odr_test.go
+++ b/light/odr_test.go
@@ -31,7 +31,7 @@ import (
"github.com/dexon-foundation/dexon/core/rawdb"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/params"
diff --git a/light/trie_test.go b/light/trie_test.go
index e0eee22e1..72b709ea6 100644
--- a/light/trie_test.go
+++ b/light/trie_test.go
@@ -26,7 +26,7 @@ import (
"github.com/dexon-foundation/dexon/consensus/ethash"
"github.com/dexon-foundation/dexon/core"
"github.com/dexon-foundation/dexon/core/state"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/params"
"github.com/dexon-foundation/dexon/trie"
diff --git a/light/txpool_test.go b/light/txpool_test.go
index b7e6fe5b3..4775261d9 100644
--- a/light/txpool_test.go
+++ b/light/txpool_test.go
@@ -27,7 +27,7 @@ import (
"github.com/dexon-foundation/dexon/consensus/ethash"
"github.com/dexon-foundation/dexon/core"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/params"
)
diff --git a/miner/worker_test.go b/miner/worker_test.go
index a3468e551..2c1c8b71a 100644
--- a/miner/worker_test.go
+++ b/miner/worker_test.go
@@ -27,7 +27,7 @@ import (
"github.com/dexon-foundation/dexon/consensus/ethash"
"github.com/dexon-foundation/dexon/core"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/event"
diff --git a/tests/block_test_util.go b/tests/block_test_util.go
index e0fdeb9d4..1bfcabd0c 100644
--- a/tests/block_test_util.go
+++ b/tests/block_test_util.go
@@ -32,7 +32,7 @@ import (
"github.com/dexon-foundation/dexon/core"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/params"
"github.com/dexon-foundation/dexon/rlp"
diff --git a/tests/state_test.go b/tests/state_test.go
index e131549b2..b5f887085 100644
--- a/tests/state_test.go
+++ b/tests/state_test.go
@@ -25,7 +25,7 @@ import (
"testing"
"github.com/dexon-foundation/dexon/cmd/utils"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
)
func TestState(t *testing.T) {
diff --git a/tests/state_test_util.go b/tests/state_test_util.go
index 310787ed2..756de5ff4 100644
--- a/tests/state_test_util.go
+++ b/tests/state_test_util.go
@@ -29,7 +29,7 @@ import (
"github.com/dexon-foundation/dexon/core"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/params"
diff --git a/tests/vm_test.go b/tests/vm_test.go
index a5d5b2ba5..b7746188c 100644
--- a/tests/vm_test.go
+++ b/tests/vm_test.go
@@ -19,7 +19,7 @@ package tests
import (
"testing"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
)
func TestVM(t *testing.T) {
diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go
index d79d18fbf..316213ea5 100644
--- a/tests/vm_test_util.go
+++ b/tests/vm_test_util.go
@@ -27,7 +27,7 @@ import (
"github.com/dexon-foundation/dexon/common/math"
"github.com/dexon-foundation/dexon/core"
"github.com/dexon-foundation/dexon/core/state"
- "github.com/dexon-foundation/dexon/core/vm"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/params"