aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJhih-Ming Huang <jm.huang@cobinhood.com>2019-02-19 11:26:49 +0800
committerJhih-Ming Huang <jm.huang@cobinhood.com>2019-05-06 10:44:04 +0800
commit156e8c3e6a06a7ba3fc35ac7dd1162493090ce29 (patch)
treeb136c746d17a6ed77879bc17be7d3f8221aa6cff
parentd7ee3523a6b67a240d9f9e4924f286586c6613b2 (diff)
downloaddexon-156e8c3e6a06a7ba3fc35ac7dd1162493090ce29.tar.gz
dexon-156e8c3e6a06a7ba3fc35ac7dd1162493090ce29.tar.zst
dexon-156e8c3e6a06a7ba3fc35ac7dd1162493090ce29.zip
core: rebase dev and fix lint
-rw-r--r--consensus/dexcon/fake_dexcon.go4
-rw-r--r--core/chain_makers.go4
-rw-r--r--core/dexon_chain_makers.go4
-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.go1061
-rw-r--r--core/vm/evm/oracle.go (renamed from core/vm/oracle.go)7
-rw-r--r--core/vm/evm/oracle_contract_abi.go (renamed from core/vm/oracle_contract_abi.go)2
-rw-r--r--core/vm/evm/oracle_contracts.go (renamed from core/vm/oracle_contracts.go)17
-rw-r--r--core/vm/evm/oracle_contracts_test.go (renamed from core/vm/oracle_contracts_test.go)13
10 files changed, 27 insertions, 4416 deletions
diff --git a/consensus/dexcon/fake_dexcon.go b/consensus/dexcon/fake_dexcon.go
index 430d9bc6b..befda7514 100644
--- a/consensus/dexcon/fake_dexcon.go
+++ b/consensus/dexcon/fake_dexcon.go
@@ -16,7 +16,7 @@ import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/consensus"
"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/rlp"
)
@@ -140,7 +140,7 @@ func (n *Node) DKGFinalize(round uint64) *coreTypesDKG.Finalize {
func (n *Node) CreateGovTx(nonce uint64, data []byte) *types.Transaction {
tx, err := types.SignTx(types.NewTransaction(
nonce,
- vm.GovernanceContractAddress,
+ evm.GovernanceContractAddress,
big.NewInt(0),
uint64(2000000),
big.NewInt(1e10),
diff --git a/core/chain_makers.go b/core/chain_makers.go
index f57eb37ff..50a537964 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -27,7 +27,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"
+ "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/params"
)
@@ -103,7 +103,7 @@ func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) {
b.SetCoinbase(common.Address{})
}
b.statedb.Prepare(tx.Hash(), common.Hash{}, len(b.txs))
- receipt, _, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vm.Config{})
+ receipt, _, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, evm.Config{})
if err != nil {
panic(err)
}
diff --git a/core/dexon_chain_makers.go b/core/dexon_chain_makers.go
index 010b30c84..6901a8bc2 100644
--- a/core/dexon_chain_makers.go
+++ b/core/dexon_chain_makers.go
@@ -28,7 +28,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"
+ "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"
@@ -110,7 +110,7 @@ func (b *DexonBlockGen) ProcessTransactions(c ChainContext) {
for _, tx := range b.txs {
b.statedb.Prepare(tx.Hash(), common.Hash{}, len(b.txs))
// TODO: fix the chain context parameter
- receipt, _, err := ApplyTransaction(b.config, c, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vm.Config{})
+ receipt, _, err := ApplyTransaction(b.config, c, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, evm.Config{})
if err != nil {
panic(err)
}
diff --git a/core/vm/evm/governance.go b/core/vm/evm/governance.go
deleted file mode 100644
index 18e733342..000000000
--- a/core/vm/evm/governance.go
+++ /dev/null
@@ -1,2198 +0,0 @@
-// 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 *vm.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 vm.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 *vm.Contract
-}
-
-func newGovernanceContract(evm *EVM, contract *vm.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
deleted file mode 100644
index 966c4c4f3..000000000
--- a/core/vm/evm/governance_abi.go
+++ /dev/null
@@ -1,1133 +0,0 @@
-// 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
deleted file mode 100644
index 5a82c7f1a..000000000
--- a/core/vm/evm/governance_test.go
+++ /dev/null
@@ -1,1061 +0,0 @@
-// 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/core/vm"
- "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 := vm.Context{
- CanTransfer: func(db vm.StateDB, addr common.Address, amount *big.Int) bool {
- return db.GetBalance(addr).Cmp(amount) >= 0
- },
- Transfer: func(db vm.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(vm.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/oracle.go b/core/vm/evm/oracle.go
index 0d4c10d9e..1daba822e 100644
--- a/core/vm/oracle.go
+++ b/core/vm/evm/oracle.go
@@ -15,13 +15,14 @@
// along with the dexon-consensus library. If not, see
// <http://www.gnu.org/licenses/>.
-package vm
+package evm
import (
"strings"
"github.com/dexon-foundation/dexon/accounts/abi"
"github.com/dexon-foundation/dexon/common"
+ "github.com/dexon-foundation/dexon/core/vm"
)
var GovernanceContractAddress = common.HexToAddress("63751838d6485578b23e8b051d40861ecc416794")
@@ -34,7 +35,7 @@ func init() {
// OracleContract represent special system contracts written in Go.
type OracleContract interface {
- Run(evm *EVM, input []byte, contract *Contract) (ret []byte, err error)
+ Run(evm *EVM, input []byte, contract *vm.Contract) (ret []byte, err error)
}
// A map representing available system oracle contracts.
@@ -47,7 +48,7 @@ var OracleContracts = map[common.Address]func() OracleContract{
}
// Run oracle contract.
-func RunOracleContract(oracle OracleContract, evm *EVM, input []byte, contract *Contract) (ret []byte, err error) {
+func RunOracleContract(oracle OracleContract, evm *EVM, input []byte, contract *vm.Contract) (ret []byte, err error) {
return oracle.Run(evm, input, contract)
}
diff --git a/core/vm/oracle_contract_abi.go b/core/vm/evm/oracle_contract_abi.go
index 0516f3891..3e7fc8784 100644
--- a/core/vm/oracle_contract_abi.go
+++ b/core/vm/evm/oracle_contract_abi.go
@@ -15,7 +15,7 @@
// along with the dexon-consensus library. If not, see
// <http://www.gnu.org/licenses/>.
-package vm
+package evm
// The governance ABI is generated from:
// https://github.com/dexon-foundation/governance-abi
diff --git a/core/vm/oracle_contracts.go b/core/vm/evm/oracle_contracts.go
index 4a3c05ccf..4a13198e2 100644
--- a/core/vm/oracle_contracts.go
+++ b/core/vm/evm/oracle_contracts.go
@@ -15,7 +15,7 @@
// along with the dexon-consensus library. If not, see
// <http://www.gnu.org/licenses/>.
-package vm
+package evm
import (
"bytes"
@@ -29,6 +29,7 @@ import (
"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/core/vm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/params"
"github.com/dexon-foundation/dexon/rlp"
@@ -124,7 +125,7 @@ func IdToAddress(id coreTypes.NodeID) common.Address {
// State manipulation helper fro the governance contract.
type GovernanceState struct {
- StateDB StateDB
+ StateDB vm.StateDB
}
func (s *GovernanceState) getState(loc common.Hash) common.Hash {
@@ -1277,7 +1278,7 @@ type tsigVerifierIntf interface {
type GovernanceContract struct {
evm *EVM
state GovernanceState
- contract *Contract
+ contract *vm.Contract
coreDKGUtils coreDKGUtils
}
@@ -1324,7 +1325,7 @@ func (g *GovernanceContract) transfer(from, to common.Address, amount *big.Int)
func (g *GovernanceContract) useGas(gas uint64) ([]byte, error) {
if !g.contract.UseGas(gas) {
- return nil, ErrOutOfGas
+ return nil, vm.ErrOutOfGas
}
return nil, nil
}
@@ -1913,17 +1914,17 @@ func (g *GovernanceContract) payFine(nodeAddr common.Address) ([]byte, error) {
}
node := g.state.Node(nodeOffset)
- if node.Fined.Cmp(big.NewInt(0)) <= 0 || node.Fined.Cmp(g.contract.Value()) < 0 {
+ 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())
+ node.Fined = new(big.Int).Sub(node.Fined, g.contract.Value)
g.state.UpdateNode(nodeOffset, node)
// Pay the fine to governance owner.
g.evm.StateDB.AddBalance(g.state.Owner(), g.contract.Value)
- g.state.emitFinePaid(nodeAddr, g.contract.Value())
+ g.state.emitFinePaid(nodeAddr, g.contract.Value)
return g.useGas(GovernanceActionGasCost)
}
@@ -2187,7 +2188,7 @@ func (g *GovernanceContract) resetDKG(newSignedCRS []byte) ([]byte, error) {
}
// Run executes governance contract.
-func (g *GovernanceContract) Run(evm *EVM, input []byte, contract *Contract) (ret []byte, err error) {
+func (g *GovernanceContract) Run(evm *EVM, input []byte, contract *vm.Contract) (ret []byte, err error) {
if len(input) < 4 {
return nil, errExecutionReverted
}
diff --git a/core/vm/oracle_contracts_test.go b/core/vm/evm/oracle_contracts_test.go
index c77313ba7..41bf0fb58 100644
--- a/core/vm/oracle_contracts_test.go
+++ b/core/vm/evm/oracle_contracts_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 (
"bytes"
@@ -36,6 +36,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/ethdb"
"github.com/dexon-foundation/dexon/params"
@@ -164,7 +165,7 @@ func TestGovernanceState(t *testing.T) {
type OracleContractsTestSuite struct {
suite.Suite
- context Context
+ context vm.Context
config *params.DexconConfig
memDB *ethdb.MemDatabase
stateDB *state.StateDB
@@ -208,11 +209,11 @@ func (g *OracleContractsTestSuite) SetupTest() {
g.stateDB.Commit(true)
- g.context = Context{
- CanTransfer: func(db StateDB, addr common.Address, amount *big.Int) bool {
+ g.context = vm.Context{
+ CanTransfer: func(db vm.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) {
+ Transfer: func(db vm.StateDB, sender common.Address, recipient common.Address, amount *big.Int) {
db.SubBalance(sender, amount)
db.AddBalance(recipient, amount)
},
@@ -249,7 +250,7 @@ func (g *OracleContractsTestSuite) call(
g.context.Time = big.NewInt(time.Now().UnixNano() / 1000000)
evm := NewEVM(g.context, g.stateDB, params.TestChainConfig, Config{IsBlockProposer: true})
- ret, _, err := evm.Call(AccountRef(caller), contractAddr, input, 10000000, value)
+ ret, _, err := evm.Call(vm.AccountRef(caller), contractAddr, input, 10000000, value)
return ret, err
}