From 47fe1c6cfd218185bfb5bb45b74434197d39cd14 Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Wed, 10 Aug 2022 16:41:45 +0700 Subject: [PATCH 01/52] feat(consortiumV2): add consortium v2 block config (#91) --- genesis/devnet.json | 1 + params/config.go | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/genesis/devnet.json b/genesis/devnet.json index 36ee5798a8..5455646ab6 100644 --- a/genesis/devnet.json +++ b/genesis/devnet.json @@ -9,6 +9,7 @@ "constantinopleBlock": 0, "petersburgBlock": 0, "istanbulBlock": 0, + "consortiumV2Block": 0, "consortium": { "period": 3, "epoch": 30 diff --git a/params/config.go b/params/config.go index 0e474231c1..0aceea8e36 100644 --- a/params/config.go +++ b/params/config.go @@ -281,16 +281,16 @@ var ( // // This configuration is intentionally not using keyed fields to force anyone // adding flags to the config to also have to set these fields. - AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, new(EthashConfig), nil, nil} + AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, nil, new(EthashConfig), nil, nil} // AllCliqueProtocolChanges contains every protocol change (EIPs) introduced // and accepted by the Ethereum core developers into the Clique consensus. // // This configuration is intentionally not using keyed fields to force anyone // adding flags to the config to also have to set these fields. - AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil} + AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil} - TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, new(EthashConfig), nil, nil} + TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, nil, new(EthashConfig), nil, nil} TestRules = TestChainConfig.Rules(new(big.Int)) ) @@ -372,6 +372,7 @@ type ChainConfig struct { ArrowGlacierBlock *big.Int `json:"arrowGlacierBlock,omitempty"` // Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already activated) OdysseusBlock *big.Int `json:"odysseusBlock,omitempty"` // Odysseus switch block (nil = no fork, 0 = already on activated) FenixBlock *big.Int `json:"fenixBlock,omitempty"` // Fenix switch block (nil = no fork, 0 = already on activated) + ConsortiumV2Block *big.Int `json:"consortiumV2Block,omitempty"` // Consortium v2 switch block (nil = no fork, 0 = already on activated) BlacklistContractAddress *common.Address `json:"blacklistContractAddress,omitempty"` // Address of Blacklist Contract (nil = no blacklist) FenixValidatorContractAddress *common.Address `json:"fenixValidatorContractAddress,omitempty"` // Address of Ronin Contract in the Fenix hardfork (nil = no blacklist) From b2fa4a87847ca4cc62c1f8fe1bf9a56f38d36c3d Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Thu, 11 Aug 2022 11:14:42 +0700 Subject: [PATCH 02/52] [RON-156] feat(consortiumV2): implement Engine interface for Consortium wrapper (#90) * feat(consortiumV2): implement Engine interface just implement empty interface, function not yet * fix(consortiumV2): remove consortium v2 * fix(consortiumV2): clean up consortium v2 * feat(consortiumV2): implement Consortium wrapper for v1 * feat(consortiumV2): implement SetGetSCValidatorsFn and SetGetFenixValidators * feat(consortiumV2): implement Authorize * fix(consortiumV2): Authorize params * fix(consortiumV2): rename consortium to main for helping review --- consensus/consortium/main.go | 104 ++++++++++++++++++++ consensus/consortium/{ => v1}/api.go | 2 +- consensus/consortium/{ => v1}/consortium.go | 4 +- consensus/consortium/{ => v1}/snapshot.go | 2 +- eth/backend.go | 2 +- eth/ethconfig/config.go | 2 +- params/config.go | 8 +- proxy/server.go | 1 - 8 files changed, 117 insertions(+), 8 deletions(-) create mode 100644 consensus/consortium/main.go rename consensus/consortium/{ => v1}/api.go (99%) rename consensus/consortium/{ => v1}/consortium.go (99%) rename consensus/consortium/{ => v1}/snapshot.go (99%) diff --git a/consensus/consortium/main.go b/consensus/consortium/main.go new file mode 100644 index 0000000000..ea42666355 --- /dev/null +++ b/consensus/consortium/main.go @@ -0,0 +1,104 @@ +package consortium + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" + v1 "github.com/ethereum/go-ethereum/consensus/consortium/v1" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rpc" + "math/big" +) + +type Consortium struct { + v1 *v1.Consortium +} + +// New creates a Consortium proof-of-authority consensus engine with the initial +// signers set to the ones provided by the user. +func New(config *params.ConsortiumConfig, db ethdb.Database) *Consortium { + // Set any missing consensus parameters to their defaults + consortiumV1 := v1.New(config, db) + + return &Consortium{ + v1: consortiumV1, + } +} + +func (c *Consortium) Author(header *types.Header) (common.Address, error) { + return c.v1.Author(header) +} + +func (c *Consortium) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { + return c.v1.VerifyHeader(chain, header, seal) +} + +func (c *Consortium) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { + var headersV1 []*types.Header + var headersV2 []*types.Header + + for _, header := range headers { + if chain.Config().IsConsortiumV2(header.Number) { + headersV2 = append(headersV2, header) + } else { + headersV1 = append(headersV1, header) + } + } + + // TODO: handle headers v2 is WIP + + return c.v1.VerifyHeaders(chain, headersV1, seals) +} + +func (c *Consortium) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { + return c.v1.VerifyUncles(chain, block) +} + +func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { + return c.v1.Prepare(chain, header) +} + +func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) { + c.v1.Finalize(chain, header, state, txs, uncles) +} + +func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { + return c.v1.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts) +} + +func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { + return c.v1.Seal(chain, block, results, stop) +} + +func (c *Consortium) SealHash(header *types.Header) common.Hash { + return c.v1.SealHash(header) +} + +func (c *Consortium) Close() error { + return nil +} + +func (c *Consortium) APIs(chain consensus.ChainHeaderReader) []rpc.API { + return c.v1.APIs(chain) +} + +func (c *Consortium) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { + return c.v1.CalcDifficulty(chain, time, parent) +} + +// Authorize backward compatible for consortium v1 +func (c *Consortium) Authorize(signer common.Address, signFn v1.SignerFn) { + c.v1.Authorize(signer, signFn) +} + +// SetGetSCValidatorsFn backward compatible for consortium v1 +func (c *Consortium) SetGetSCValidatorsFn(fn func() ([]common.Address, error)) { + c.v1.SetGetFenixValidators(fn) +} + +// SetGetFenixValidators backward compatible for consortium v1 +func (c *Consortium) SetGetFenixValidators(fn func() ([]common.Address, error)) { + c.v1.SetGetFenixValidators(fn) +} diff --git a/consensus/consortium/api.go b/consensus/consortium/v1/api.go similarity index 99% rename from consensus/consortium/api.go rename to consensus/consortium/v1/api.go index a4773f628d..a62b61f70d 100644 --- a/consensus/consortium/api.go +++ b/consensus/consortium/v1/api.go @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package consortium +package v1 import ( "github.com/ethereum/go-ethereum/common" diff --git a/consensus/consortium/consortium.go b/consensus/consortium/v1/consortium.go similarity index 99% rename from consensus/consortium/consortium.go rename to consensus/consortium/v1/consortium.go index e40b6e56d9..68455fe8c9 100644 --- a/consensus/consortium/consortium.go +++ b/consensus/consortium/v1/consortium.go @@ -14,8 +14,8 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// Package consortium implements the proof-of-authority consensus engine. -package consortium +// Package v1 implements the proof-of-authority consensus engine. +package v1 import ( "bytes" diff --git a/consensus/consortium/snapshot.go b/consensus/consortium/v1/snapshot.go similarity index 99% rename from consensus/consortium/snapshot.go rename to consensus/consortium/v1/snapshot.go index b36bdbf593..a648285534 100644 --- a/consensus/consortium/snapshot.go +++ b/consensus/consortium/v1/snapshot.go @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -package consortium +package v1 import ( "encoding/json" diff --git a/eth/backend.go b/eth/backend.go index 6c93e3a810..36b8ffd7df 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -20,6 +20,7 @@ package eth import ( "errors" "fmt" + "github.com/ethereum/go-ethereum/consensus/consortium" "math/big" "runtime" "sync" @@ -33,7 +34,6 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/clique" - "github.com/ethereum/go-ethereum/consensus/consortium" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/bloombits" "github.com/ethereum/go-ethereum/core/rawdb" diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 34bfeb1017..bef34bfc14 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -18,6 +18,7 @@ package ethconfig import ( + "github.com/ethereum/go-ethereum/consensus/consortium" "math/big" "os" "os/user" @@ -28,7 +29,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/clique" - "github.com/ethereum/go-ethereum/consensus/consortium" "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/eth/downloader" diff --git a/params/config.go b/params/config.go index 0aceea8e36..b6007b44cb 100644 --- a/params/config.go +++ b/params/config.go @@ -539,6 +539,11 @@ func (c *ChainConfig) IsFenix(num *big.Int) bool { return isForked(c.FenixBlock, num) } +// IsConsortiumV2 returns whether the num is equals to or larger than the Fenix fork block. +func (c *ChainConfig) IsConsortiumV2(num *big.Int) bool { + return isForked(c.ConsortiumV2Block, num) +} + // CheckCompatible checks whether scheduled fork transitions have been imported // with a mismatching chain configuration. func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64) *ConfigCompatError { @@ -726,7 +731,7 @@ type Rules struct { IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool IsBerlin, IsLondon bool - IsOdysseusFork, IsFenix bool + IsOdysseusFork, IsFenix, IsConsortiumV2 bool } // Rules ensures c's ChainID is not nil. @@ -749,5 +754,6 @@ func (c *ChainConfig) Rules(num *big.Int) Rules { IsLondon: c.IsLondon(num), IsOdysseusFork: c.IsOdysseus(num), IsFenix: c.IsFenix(num), + IsConsortiumV2: c.IsConsortiumV2(num), } } diff --git a/proxy/server.go b/proxy/server.go index f355d6df66..0d254eafd4 100644 --- a/proxy/server.go +++ b/proxy/server.go @@ -13,7 +13,6 @@ import ( "time" ) - // Server is a proxy server that simulates rpc structures, // it uses http database which remotely connects to other rpc nodes to get and cache data if needed // it can be used to get data from rpc and cache them From 1804181c6aa4f9745246fd12646ff7b325c53786 Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Thu, 11 Aug 2022 13:19:34 +0700 Subject: [PATCH 03/52] [RON-156] feat(consortiumV2): implement Consortium v2 interface (#92) * feat(consortiumV2): implement Consortium v2 interface * feat(consortiumV2): implement logic for Consortium wrapper to call v2 or v1 --- consensus/consortium/common/constants.go | 16 +++ consensus/consortium/common/types.go | 7 ++ consensus/consortium/common/utils.go | 81 ++++++++++++++ consensus/consortium/main.go | 98 +++++++++++++---- consensus/consortium/v1/consortium.go | 125 ++++------------------ consensus/consortium/v1/snapshot.go | 3 +- consensus/consortium/v2/consortium.go | 128 +++++++++++++++++++++++ consensus/consortium/v2/snapshot.go | 35 +++++++ eth/ethconfig/config.go | 2 +- proxy/backend.go | 2 +- proxy/server.go | 2 +- 11 files changed, 372 insertions(+), 127 deletions(-) create mode 100644 consensus/consortium/common/constants.go create mode 100644 consensus/consortium/common/types.go create mode 100644 consensus/consortium/common/utils.go create mode 100644 consensus/consortium/v2/consortium.go create mode 100644 consensus/consortium/v2/snapshot.go diff --git a/consensus/consortium/common/constants.go b/consensus/consortium/common/constants.go new file mode 100644 index 0000000000..2c836dfdbd --- /dev/null +++ b/consensus/consortium/common/constants.go @@ -0,0 +1,16 @@ +package common + +import ( + "errors" + "github.com/ethereum/go-ethereum/crypto" +) + +var ( + ExtraSeal = crypto.SignatureLength // Fixed number of extra-data suffix bytes reserved for signer seal +) + +var ( + // ErrMissingSignature is returned if a block's extra-data section doesn't seem + // to contain a 65 byte secp256k1 signature. + ErrMissingSignature = errors.New("extra-data 65 byte signature suffix missing") +) diff --git a/consensus/consortium/common/types.go b/consensus/consortium/common/types.go new file mode 100644 index 0000000000..3972f8cfc4 --- /dev/null +++ b/consensus/consortium/common/types.go @@ -0,0 +1,7 @@ +package common + +import "github.com/ethereum/go-ethereum/accounts" + +// SignerFn is a signer callback function to request a header to be signed by a +// backing account. +type SignerFn func(accounts.Account, string, []byte) ([]byte, error) diff --git a/consensus/consortium/common/utils.go b/consensus/consortium/common/utils.go new file mode 100644 index 0000000000..5c29edcc0e --- /dev/null +++ b/consensus/consortium/common/utils.go @@ -0,0 +1,81 @@ +package common + +import ( + "bytes" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/rlp" + lru "github.com/hashicorp/golang-lru" + "golang.org/x/crypto/sha3" + "io" +) + +// Ecrecover extracts the Ethereum account address from a signed header. +func Ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) { + // If the signature's already cached, return that + hash := header.Hash() + if address, known := sigcache.Get(hash); known { + return address.(common.Address), nil + } + // Retrieve the signature from the header extra-data + if len(header.Extra) < ExtraSeal { + return common.Address{}, ErrMissingSignature + } + signature := header.Extra[len(header.Extra)-ExtraSeal:] + + // Recover the public key and the Ethereum address + pubkey, err := crypto.Ecrecover(SealHash(header).Bytes(), signature) + if err != nil { + return common.Address{}, err + } + var signer common.Address + copy(signer[:], crypto.Keccak256(pubkey[1:])[12:]) + + sigcache.Add(hash, signer) + return signer, nil +} + +// SealHash returns the hash of a block prior to it being sealed. +func SealHash(header *types.Header) (hash common.Hash) { + hasher := sha3.NewLegacyKeccak256() + encodeSigHeader(hasher, header) + hasher.Sum(hash[:0]) + return hash +} + +// ConsortiumRLP returns the rlp bytes which needs to be signed for the proof-of-authority +// sealing. The RLP to sign consists of the entire header apart from the 65 byte signature +// contained at the end of the extra data. +// +// Note, the method requires the extra data to be at least 65 bytes, otherwise it +// panics. This is done to avoid accidentally using both forms (signature present +// or not), which could be abused to produce different hashes for the same header. +func ConsortiumRLP(header *types.Header) []byte { + b := new(bytes.Buffer) + encodeSigHeader(b, header) + return b.Bytes() +} + +func encodeSigHeader(w io.Writer, header *types.Header) { + err := rlp.Encode(w, []interface{}{ + header.ParentHash, + header.UncleHash, + header.Coinbase, + header.Root, + header.TxHash, + header.ReceiptHash, + header.Bloom, + header.Difficulty, + header.Number, + header.GasLimit, + header.GasUsed, + header.Time, + header.Extra[:len(header.Extra)-crypto.SignatureLength], // Yes, this will panic if extra is too short + header.MixDigest, + header.Nonce, + }) + if err != nil { + panic("can't encode: " + err.Error()) + } +} diff --git a/consensus/consortium/main.go b/consensus/consortium/main.go index ea42666355..60e1852210 100644 --- a/consensus/consortium/main.go +++ b/consensus/consortium/main.go @@ -3,7 +3,9 @@ package consortium import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" + consortiumCommon "github.com/ethereum/go-ethereum/consensus/consortium/common" v1 "github.com/ethereum/go-ethereum/consensus/consortium/v1" + v2 "github.com/ethereum/go-ethereum/consensus/consortium/v2" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" @@ -13,83 +15,139 @@ import ( ) type Consortium struct { - v1 *v1.Consortium + v1 *v1.Consortium + v2 *v2.Consortium + isConsortiumV2 func(num *big.Int) bool } -// New creates a Consortium proof-of-authority consensus engine with the initial +// New creates a Consortium proof-of-stake consensus engine with the initial // signers set to the ones provided by the user. -func New(config *params.ConsortiumConfig, db ethdb.Database) *Consortium { +func New(config *params.ChainConfig, db ethdb.Database) *Consortium { // Set any missing consensus parameters to their defaults - consortiumV1 := v1.New(config, db) + consortiumV1 := v1.New(config.Consortium, db) + consortiumV2 := v2.New(config.Consortium, db) return &Consortium{ - v1: consortiumV1, + v1: consortiumV1, + v2: consortiumV2, + isConsortiumV2: config.IsConsortiumV2, } } +// Author since v1 and v2 are implemented the same logic, so we don't need to check whether the current block is version 1 +// or version 2 func (c *Consortium) Author(header *types.Header) (common.Address, error) { return c.v1.Author(header) } func (c *Consortium) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { + if chain.Config().IsConsortiumV2(header.Number) { + return c.v2.VerifyHeader(chain, header, seal) + } + return c.v1.VerifyHeader(chain, header, seal) } func (c *Consortium) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { - var headersV1 []*types.Header - var headersV2 []*types.Header - - for _, header := range headers { - if chain.Config().IsConsortiumV2(header.Number) { - headersV2 = append(headersV2, header) - } else { - headersV1 = append(headersV1, header) + abort := make(chan struct{}) + results := make(chan error, len(headers)) + + go func() { + for i, header := range headers { + var err error + if c.isConsortiumV2(header.Number) { + err = c.v2.VerifyHeaderAndParents(chain, header, headers[:i]) + } else { + err = c.v1.VerifyHeaderAndParents(chain, header, headers[:i]) + } + + select { + case <-abort: + return + case results <- err: + } } - } + }() - // TODO: handle headers v2 is WIP - - return c.v1.VerifyHeaders(chain, headersV1, seals) + return abort, results } func (c *Consortium) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { + if c.isConsortiumV2(block.Header().Number) { + return c.v2.VerifyUncles(chain, block) + } + return c.v1.VerifyUncles(chain, block) } func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { + if c.isConsortiumV2(header.Number) { + return c.v2.Prepare(chain, header) + } + return c.v1.Prepare(chain, header) } func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) { - c.v1.Finalize(chain, header, state, txs, uncles) + if c.isConsortiumV2(header.Number) { + c.v2.Finalize(chain, header, state, txs, uncles) + } else { + c.v1.Finalize(chain, header, state, txs, uncles) + } } func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { + if c.isConsortiumV2(header.Number) { + return c.v2.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts) + } + return c.v1.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts) } func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { + if c.isConsortiumV2(block.Header().Number) { + return c.v2.Seal(chain, block, results, stop) + } + return c.v1.Seal(chain, block, results, stop) } func (c *Consortium) SealHash(header *types.Header) common.Hash { + if c.isConsortiumV2(header.Number) { + return c.v2.SealHash(header) + } + return c.v1.SealHash(header) } +// Close since v1 and v2 are implemented the same logic, so we don't need to check whether the current block is version 1 +// or version 2 func (c *Consortium) Close() error { return nil } +// APIs doesn't need to check whether the current block is v1 or v2 because in proxy/server.go create empty +// params.ChainConfig{} so we can't use it. func (c *Consortium) APIs(chain consensus.ChainHeaderReader) []rpc.API { - return c.v1.APIs(chain) + var apis []rpc.API + apisV1 := c.v1.APIs(chain) + apisV2 := c.v2.APIs(chain) + apis = append(apis, apisV1...) + apis = append(apis, apisV2...) + + return apis } func (c *Consortium) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { + if c.isConsortiumV2(parent.Number) { + return c.v2.CalcDifficulty(chain, time, parent) + } + return c.v1.CalcDifficulty(chain, time, parent) } // Authorize backward compatible for consortium v1 -func (c *Consortium) Authorize(signer common.Address, signFn v1.SignerFn) { +func (c *Consortium) Authorize(signer common.Address, signFn consortiumCommon.SignerFn) { c.v1.Authorize(signer, signFn) } diff --git a/consensus/consortium/v1/consortium.go b/consensus/consortium/v1/consortium.go index 68455fe8c9..5c2b6299e5 100644 --- a/consensus/consortium/v1/consortium.go +++ b/consensus/consortium/v1/consortium.go @@ -20,7 +20,6 @@ package v1 import ( "bytes" "errors" - "io" "math/big" "math/rand" "sync" @@ -30,18 +29,16 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/consensus" + consortiumCommon "github.com/ethereum/go-ethereum/consensus/consortium/common" "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/trie" lru "github.com/hashicorp/golang-lru" - "golang.org/x/crypto/sha3" ) const ( @@ -55,8 +52,7 @@ const ( var ( epochLength = uint64(30000) // Default number of blocks after which to checkpoint - extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity - extraSeal = crypto.SignatureLength // Fixed number of extra-data suffix bytes reserved for signer seal + extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity emptyNonce = hexutil.MustDecode("0x0000000000000000") // Nonce number should be empty @@ -86,10 +82,6 @@ var ( // 32 bytes, which is required to store the signer vanity. errMissingVanity = errors.New("extra-data 32 byte vanity prefix missing") - // errMissingSignature is returned if a block's extra-data section doesn't seem - // to contain a 65 byte secp256k1 signature. - errMissingSignature = errors.New("extra-data 65 byte signature suffix missing") - // errExtraSigners is returned if non-checkpoint block contain signer data in // their extra-data fields. errExtraSigners = errors.New("non-checkpoint block contains extra signer list") @@ -131,35 +123,6 @@ var ( errWrongCoinbase = errors.New("wrong coinbase address") ) -// SignerFn is a signer callback function to request a header to be signed by a -// backing account. -type SignerFn func(accounts.Account, string, []byte) ([]byte, error) - -// ecrecover extracts the Ethereum account address from a signed header. -func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) { - // If the signature's already cached, return that - hash := header.Hash() - if address, known := sigcache.Get(hash); known { - return address.(common.Address), nil - } - // Retrieve the signature from the header extra-data - if len(header.Extra) < extraSeal { - return common.Address{}, errMissingSignature - } - signature := header.Extra[len(header.Extra)-extraSeal:] - - // Recover the public key and the Ethereum address - pubkey, err := crypto.Ecrecover(SealHash(header).Bytes(), signature) - if err != nil { - return common.Address{}, err - } - var signer common.Address - copy(signer[:], crypto.Keccak256(pubkey[1:])[12:]) - - sigcache.Add(hash, signer) - return signer, nil -} - // Consortium is the proof-of-authority consensus engine proposed to support the // Ethereum testnet following the Ropsten attacks. type Consortium struct { @@ -171,9 +134,9 @@ type Consortium struct { proposals map[common.Address]bool // Current list of proposals we are pushing - signer common.Address // Ethereum address of the signing key - signFn SignerFn // Signer function to authorize hashes with - lock sync.RWMutex // Protects the signer fields + signer common.Address // Ethereum address of the signing key + signFn consortiumCommon.SignerFn // Signer function to authorize hashes with + lock sync.RWMutex // Protects the signer fields getSCValidators func() ([]common.Address, error) // Get the list of validator from contract getFenixValidators func() ([]common.Address, error) // Get the validator list from Ronin Validator contract of Fenix hardfork @@ -213,12 +176,12 @@ func (c *Consortium) SetGetFenixValidators(fn func() ([]common.Address, error)) // Author implements consensus.Engine, returning the Ethereum address recovered // from the signature in the header's extra-data section. func (c *Consortium) Author(header *types.Header) (common.Address, error) { - return ecrecover(header, c.signatures) + return consortiumCommon.Ecrecover(header, c.signatures) } // VerifyHeader checks whether a header conforms to the consensus rules. func (c *Consortium) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { - return c.verifyHeader(chain, header, nil) + return c.VerifyHeaderAndParents(chain, header, nil) } // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers. The @@ -230,7 +193,7 @@ func (c *Consortium) VerifyHeaders(chain consensus.ChainHeaderReader, headers [] go func() { for i, header := range headers { - err := c.verifyHeader(chain, header, headers[:i]) + err := c.VerifyHeaderAndParents(chain, header, headers[:i]) select { case <-abort: @@ -242,11 +205,11 @@ func (c *Consortium) VerifyHeaders(chain consensus.ChainHeaderReader, headers [] return abort, results } -// verifyHeader checks whether a header conforms to the consensus rules.The +// VerifyHeaderAndParents checks whether a header conforms to the consensus rules.The // caller may optionally pass in a batch of parents (ascending order) to avoid // looking those up from the database. This is useful for concurrently verifying // a batch of new headers. -func (c *Consortium) verifyHeader(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error { +func (c *Consortium) VerifyHeaderAndParents(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error { if header.Number == nil { return errUnknownBlock } @@ -264,12 +227,12 @@ func (c *Consortium) verifyHeader(chain consensus.ChainHeaderReader, header *typ if len(header.Extra) < extraVanity { return errMissingVanity } - if len(header.Extra) < extraVanity+extraSeal { - return errMissingSignature + if len(header.Extra) < extraVanity+consortiumCommon.ExtraSeal { + return consortiumCommon.ErrMissingSignature } // Ensure that the extra-data contains a signer list on checkpoint, but none otherwise checkpoint := (number % c.config.Epoch) == 0 - signersBytes := len(header.Extra) - extraVanity - extraSeal + signersBytes := len(header.Extra) - extraVanity - consortiumCommon.ExtraSeal if !checkpoint && signersBytes != 0 { return errExtraSigners } @@ -332,7 +295,7 @@ func (c *Consortium) verifyCascadingFields(chain consensus.ChainHeaderReader, he return err } - extraSuffix := len(header.Extra) - extraSeal + extraSuffix := len(header.Extra) - consortiumCommon.ExtraSeal checkpointHeaders := extractAddressFromBytes(header.Extra[extraVanity:extraSuffix]) validSigners := compareSignersLists(checkpointHeaders, signers) if !validSigners { @@ -474,7 +437,7 @@ func (c *Consortium) verifySeal(chain consensus.ChainHeaderReader, header *types } // Resolve the authorization key and check against signers - signer, err := ecrecover(header, c.signatures) + signer, err := consortiumCommon.Ecrecover(header, c.signatures) if err != nil { return err } @@ -530,7 +493,7 @@ func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.He header.Extra = append(header.Extra, signer[:]...) } } - header.Extra = append(header.Extra, make([]byte, extraSeal)...) + header.Extra = append(header.Extra, make([]byte, consortiumCommon.ExtraSeal)...) // Mix digest is reserved for now, set to empty header.MixDigest = common.Hash{} @@ -568,7 +531,7 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head // Authorize injects a private key into the consensus engine to mint new blocks // with. -func (c *Consortium) Authorize(signer common.Address, signFn SignerFn) { +func (c *Consortium) Authorize(signer common.Address, signFn consortiumCommon.SignerFn) { c.lock.Lock() defer c.lock.Unlock() @@ -626,11 +589,11 @@ func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, log.Trace("Out-of-turn signing requested", "wiggle", common.PrettyDuration(wiggle)) } // Sign all the things! - sighash, err := signFn(accounts.Account{Address: signer}, accounts.MimetypeTextPlain, ConsortiumRLP(header)) + sighash, err := signFn(accounts.Account{Address: signer}, accounts.MimetypeTextPlain, consortiumCommon.ConsortiumRLP(header)) if err != nil { return err } - copy(header.Extra[len(header.Extra)-extraSeal:], sighash) + copy(header.Extra[len(header.Extra)-consortiumCommon.ExtraSeal:], sighash) // Wait until sealing is terminated or delay timeout. log.Trace("Waiting for slot to sign and propagate", "delay", common.PrettyDuration(delay)) go func() { @@ -643,7 +606,7 @@ func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, select { case results <- block.WithSeal(header): default: - log.Warn("Sealing result is not read by miner", "sealhash", SealHash(header)) + log.Warn("Sealing result is not read by miner", "sealhash", consortiumCommon.SealHash(header)) } }() @@ -652,7 +615,7 @@ func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, // SealHash returns the hash of a block prior to it being sealed. func (c *Consortium) SealHash(header *types.Header) common.Hash { - return SealHash(header) + return consortiumCommon.SealHash(header) } // Close implements consensus.Engine. It's a noop for consortium as there are no background threads. @@ -681,50 +644,6 @@ func (c *Consortium) CalcDifficulty(chain consensus.ChainHeaderReader, time uint return c.doCalcDifficulty(c.signer, number, validators) } -// SealHash returns the hash of a block prior to it being sealed. -func SealHash(header *types.Header) (hash common.Hash) { - hasher := sha3.NewLegacyKeccak256() - encodeSigHeader(hasher, header) - hasher.Sum(hash[:0]) - return hash -} - -// ConsortiumRLP returns the rlp bytes which needs to be signed for the proof-of-authority -// sealing. The RLP to sign consists of the entire header apart from the 65 byte signature -// contained at the end of the extra data. -// -// Note, the method requires the extra data to be at least 65 bytes, otherwise it -// panics. This is done to avoid accidentally using both forms (signature present -// or not), which could be abused to produce different hashes for the same header. -func ConsortiumRLP(header *types.Header) []byte { - b := new(bytes.Buffer) - encodeSigHeader(b, header) - return b.Bytes() -} - -func encodeSigHeader(w io.Writer, header *types.Header) { - err := rlp.Encode(w, []interface{}{ - header.ParentHash, - header.UncleHash, - header.Coinbase, - header.Root, - header.TxHash, - header.ReceiptHash, - header.Bloom, - header.Difficulty, - header.Number, - header.GasLimit, - header.GasUsed, - header.Time, - header.Extra[:len(header.Extra)-crypto.SignatureLength], // Yes, this will panic if extra is too short - header.MixDigest, - header.Nonce, - }) - if err != nil { - panic("can't encode: " + err.Error()) - } -} - func signerInList(signer common.Address, validators []common.Address) bool { for _, validator := range validators { if signer == validator { @@ -789,7 +708,7 @@ func (c *Consortium) getValidatorsFromLastCheckpoint(chain consensus.ChainHeader if header == nil { header = chain.GetHeaderByNumber(lastCheckpoint) } - extraSuffix := len(header.Extra) - extraSeal + extraSuffix := len(header.Extra) - consortiumCommon.ExtraSeal return extractAddressFromBytes(header.Extra[extraVanity:extraSuffix]), nil } diff --git a/consensus/consortium/v1/snapshot.go b/consensus/consortium/v1/snapshot.go index a648285534..9d6b8f8251 100644 --- a/consensus/consortium/v1/snapshot.go +++ b/consensus/consortium/v1/snapshot.go @@ -18,6 +18,7 @@ package v1 import ( "encoding/json" + consortiumCommon "github.com/ethereum/go-ethereum/consensus/consortium/common" "time" "github.com/ethereum/go-ethereum/common" @@ -135,7 +136,7 @@ func (s *Snapshot) apply(chain consensus.ChainHeaderReader, c *Consortium, heade } // Resolve the authorization key and check against signers - signer, err := ecrecover(header, s.sigcache) + signer, err := consortiumCommon.Ecrecover(header, s.sigcache) if err != nil { return nil, err } diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go new file mode 100644 index 0000000000..95d813af8f --- /dev/null +++ b/consensus/consortium/v2/consortium.go @@ -0,0 +1,128 @@ +package v2 + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/consensus" + consortiumCommon "github.com/ethereum/go-ethereum/consensus/consortium/common" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rpc" + lru "github.com/hashicorp/golang-lru" + "math/big" + "sync" + "time" +) + +const ( + inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory + inmemorySignatures = 4096 // Number of recent block signatures to keep in memory + + wiggleTime = 1000 * time.Millisecond // Random delay (per signer) to allow concurrent signers +) + +// Consortium proof-of-authority protocol constants. +var ( + epochLength = uint64(30000) // Default number of blocks after which to checkpoint + + extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity + extraSeal = crypto.SignatureLength // Fixed number of extra-data suffix bytes reserved for signer seal + + emptyNonce = hexutil.MustDecode("0x0000000000000000") // Nonce number should be empty + + uncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW + + diffInTurn = big.NewInt(7) // Block difficulty for in-turn signatures + diffNoTurn = big.NewInt(3) // Block difficulty for out-of-turn signatures +) + +type Consortium struct { + config *params.ConsortiumConfig // Consensus engine configuration parameters + db ethdb.Database // Database to store and retrieve snapshot checkpoints + + recents *lru.ARCCache // Snapshots for recent block to speed up reorgs + signatures *lru.ARCCache // Signatures of recent blocks to speed up mining + + proposals map[common.Address]bool // Current list of proposals we are pushing + + signer common.Address // Ethereum address of the signing key + signFn consortiumCommon.SignerFn // Signer function to authorize hashes with + lock sync.RWMutex // Protects the signer fields +} + +func New(config *params.ConsortiumConfig, db ethdb.Database) *Consortium { + // Set any missing consensus parameters to their defaults + conf := *config + if conf.Epoch == 0 { + conf.Epoch = epochLength + } + // Allocate the snapshot caches and create the engine + recents, _ := lru.NewARC(inmemorySnapshots) + signatures, _ := lru.NewARC(inmemorySignatures) + + return &Consortium{ + config: &conf, + db: db, + recents: recents, + signatures: signatures, + proposals: make(map[common.Address]bool), + } +} + +func (c *Consortium) Author(header *types.Header) (common.Address, error) { + return common.Address{}, nil +} + +func (c *Consortium) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { + return nil +} + +func (c *Consortium) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { + abort := make(chan struct{}) + results := make(chan error, len(headers)) + + return abort, results +} + +func (c *Consortium) VerifyHeaderAndParents(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error { + return nil +} + +func (c *Consortium) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { + return nil +} + +func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { + return nil +} + +func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) { + +} + +func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { + return nil, nil +} + +func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { + return nil +} + +func (c *Consortium) SealHash(header *types.Header) common.Hash { + return common.Hash{} +} + +func (c *Consortium) Close() error { + return nil +} + +func (c *Consortium) APIs(chain consensus.ChainHeaderReader) []rpc.API { + return []rpc.API{} +} + +func (c *Consortium) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { + return nil +} diff --git a/consensus/consortium/v2/snapshot.go b/consensus/consortium/v2/snapshot.go new file mode 100644 index 0000000000..960fc00f44 --- /dev/null +++ b/consensus/consortium/v2/snapshot.go @@ -0,0 +1,35 @@ +package v2 + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/params" + lru "github.com/hashicorp/golang-lru" +) + +type Snapshot struct { +} + +func newSnapshot(config *params.ConsortiumConfig, sigcache *lru.ARCCache, number uint64, hash common.Hash, signers []common.Address) *Snapshot { + snap := &Snapshot{} + + return snap +} + +func loadSnapshot(config *params.ConsortiumConfig, sigcache *lru.ARCCache, db ethdb.Database, hash common.Hash) (*Snapshot, error) { + return nil, nil +} + +func (s *Snapshot) store(db ethdb.Database) error { + return nil +} + +func (s *Snapshot) copy() *Snapshot { + return nil +} + +func (s *Snapshot) apply(chain consensus.ChainHeaderReader, c *Consortium, headers []*types.Header, parents []*types.Header) (*Snapshot, error) { + return nil, nil +} diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index bef34bfc14..ca1a698899 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -214,7 +214,7 @@ func CreateConsensusEngine(stack *node.Node, chainConfig *params.ChainConfig, co return clique.New(chainConfig.Clique, db) } if chainConfig.Consortium != nil { - return consortium.New(chainConfig.Consortium, db) + return consortium.New(chainConfig, db) } // Otherwise assume proof-of-work switch config.PowMode { diff --git a/proxy/backend.go b/proxy/backend.go index b2a6dccb2a..c0a8ef7ae6 100644 --- a/proxy/backend.go +++ b/proxy/backend.go @@ -431,7 +431,7 @@ func (b *backend) ChainConfig() *params.ChainConfig { } func (b *backend) Engine() consensus.Engine { - return consortium.New(¶ms.ConsortiumConfig{}, b.db) + return consortium.New(b.ChainConfig(), b.db) } func (b *backend) GetHeader(hash common.Hash, number uint64) *types.Header { diff --git a/proxy/server.go b/proxy/server.go index 0d254eafd4..fb85a4632a 100644 --- a/proxy/server.go +++ b/proxy/server.go @@ -59,7 +59,7 @@ func NewServer(config *Config, ethConfig *ethconfig.Config, nodeConfig *node.Con } func (s *Server) Start() { - engine := consortium.New(¶ms.ConsortiumConfig{}, s.backend.db) + engine := consortium.New(¶ms.ChainConfig{}, s.backend.db) var apis = []rpc.API{ { Namespace: "eth", From 69eef5740dfe5eeb8bb8a51e9cb6a321b0236b25 Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Thu, 11 Aug 2022 15:53:45 +0700 Subject: [PATCH 04/52] Add systemcontracts and function to trigger systemcontracts at forked block number (#93) --- core/chain_makers.go | 5 ++ core/genesis.go | 2 + core/state_processor.go | 4 ++ core/systemcontracts/const.go | 9 +++ core/systemcontracts/upgrade.go | 105 ++++++++++++++++++++++++++++++++ miner/worker.go | 5 ++ params/config.go | 7 ++- 7 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 core/systemcontracts/const.go create mode 100644 core/systemcontracts/upgrade.go diff --git a/core/chain_makers.go b/core/chain_makers.go index d9b03e9e9f..5db79506f8 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -18,6 +18,7 @@ package core import ( "fmt" + "github.com/ethereum/go-ethereum/core/systemcontracts" "math/big" "github.com/ethereum/go-ethereum/common" @@ -217,6 +218,10 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse if config.DAOForkSupport && config.DAOForkBlock != nil && config.DAOForkBlock.Cmp(b.header.Number) == 0 { misc.ApplyDAOHardFork(statedb) } + + // check and apply system contracts before finalizing block + systemcontracts.UpgradeBuildInSystemContract(config, b.header.Number, statedb) + // Execute any user modifications to the block if gen != nil { gen(i, b) diff --git a/core/genesis.go b/core/genesis.go index 60c9cee186..009037a2d1 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -22,6 +22,7 @@ import ( "encoding/json" "errors" "fmt" + "github.com/ethereum/go-ethereum/core/systemcontracts" "math/big" "strings" @@ -164,6 +165,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, override } // Just commit the new block if there is no stored genesis block. stored := rawdb.ReadCanonicalHash(db, 0) + systemcontracts.GenesisHash = stored if (stored == common.Hash{}) { if genesis == nil { log.Info("Writing default main-net genesis block") diff --git a/core/state_processor.go b/core/state_processor.go index e5bfbd552a..2971f86b11 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -18,6 +18,7 @@ package core import ( "fmt" + "github.com/ethereum/go-ethereum/core/systemcontracts" "math/big" "github.com/ethereum/go-ethereum/common" @@ -70,6 +71,9 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 { misc.ApplyDAOHardFork(statedb) } + // update system contracts before processing EVM + systemcontracts.UpgradeBuildInSystemContract(p.config, block.Number(), statedb) + blockContext := NewEVMBlockContext(header, p.bc, nil, publishEvents...) vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg) // Iterate over and process the individual transactions diff --git a/core/systemcontracts/const.go b/core/systemcontracts/const.go new file mode 100644 index 0000000000..d877d5124f --- /dev/null +++ b/core/systemcontracts/const.go @@ -0,0 +1,9 @@ +package systemcontracts + +const ( + ValidatorContract = "0x0000000000000000000000000000000000001000" + SlashContract = "0x0000000000000000000000000000000000001001" + + ConsortiumV2ValidatorContractCode = "" + ConsortiumV2SlashContractCode = "" +) diff --git a/core/systemcontracts/upgrade.go b/core/systemcontracts/upgrade.go new file mode 100644 index 0000000000..705aeb29d0 --- /dev/null +++ b/core/systemcontracts/upgrade.go @@ -0,0 +1,105 @@ +package systemcontracts + +import ( + "encoding/hex" + "fmt" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" + "math/big" +) + +type UpgradeConfig struct { + BeforeUpgrade upgradeHook + AfterUpgrade upgradeHook + ContractAddr common.Address + CommitUrl string + Code string +} + +type Upgrade struct { + UpgradeName string + Configs []*UpgradeConfig +} + +type upgradeHook func(blockNumber *big.Int, contractAddr common.Address, statedb *state.StateDB) error + +const ( + mainnet = "mainnet" + testnet = "testnet" +) + +var ( + GenesisHash common.Hash + //upgrade config + consortiumV2 = make(map[string]*Upgrade) +) + +func init() { + consortiumV2[mainnet] = &Upgrade{ + UpgradeName: "consortium v2", + Configs: []*UpgradeConfig{ + { + ContractAddr: common.HexToAddress(ValidatorContract), + CommitUrl: "", + Code: ConsortiumV2ValidatorContractCode, + }, + { + ContractAddr: common.HexToAddress(SlashContract), + CommitUrl: "", + Code: ConsortiumV2SlashContractCode, + }, + }, + } + consortiumV2[testnet] = consortiumV2[mainnet] +} + +func UpgradeBuildInSystemContract(config *params.ChainConfig, blockNumber *big.Int, statedb *state.StateDB) { + if config == nil || blockNumber == nil || statedb == nil { + return + } + var network string + switch GenesisHash { + /* Add mainnet genesis hash */ + case params.RoninMainnetGenesisHash: + network = mainnet + default: + network = testnet + } + + if config.IsOnConsortiumV2(blockNumber) { + applySystemContractUpgrade(consortiumV2[network], blockNumber, statedb) + } + +} + +func applySystemContractUpgrade(upgrade *Upgrade, blockNumber *big.Int, statedb *state.StateDB) { + if upgrade == nil { + log.Info("Empty upgrade config", "height", blockNumber.String()) + return + } + + log.Info(fmt.Sprintf("Apply upgrade %s at height %d", upgrade.UpgradeName, blockNumber.Int64())) + for _, cfg := range upgrade.Configs { + log.Info(fmt.Sprintf("Upgrade contract %s to commit %s", cfg.ContractAddr.String(), cfg.CommitUrl)) + + if cfg.BeforeUpgrade != nil { + if err := cfg.BeforeUpgrade(blockNumber, cfg.ContractAddr, statedb); err != nil { + panic(fmt.Errorf("contract address: %s, execute beforeUpgrade error: %s", cfg.ContractAddr.String(), err.Error())) + } + } + + newContractCode, err := hex.DecodeString(cfg.Code) + if err != nil { + panic(fmt.Errorf("failed to decode new contract code: %s", err.Error())) + } + statedb.SetCode(cfg.ContractAddr, newContractCode) + + if cfg.AfterUpgrade != nil { + if err := cfg.AfterUpgrade(blockNumber, cfg.ContractAddr, statedb); err != nil { + panic(fmt.Errorf("contract address: %s, execute afterUpgrade error: %s", cfg.ContractAddr.String(), err.Error())) + } + } + } +} diff --git a/miner/worker.go b/miner/worker.go index aeff210641..4631dd1ce1 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -19,6 +19,7 @@ package miner import ( "bytes" "errors" + "github.com/ethereum/go-ethereum/core/systemcontracts" "math/big" "sync" "sync/atomic" @@ -964,6 +965,10 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) if w.chainConfig.DAOForkSupport && w.chainConfig.DAOForkBlock != nil && w.chainConfig.DAOForkBlock.Cmp(header.Number) == 0 { misc.ApplyDAOHardFork(env.state) } + + // Handle upgrade build-in system contract code + systemcontracts.UpgradeBuildInSystemContract(w.chainConfig, header.Number, env.state) + // Accumulate the uncles for the current block uncles := make([]*types.Header, 0, 2) commitUncles := func(blocks map[common.Hash]*types.Block) { diff --git a/params/config.go b/params/config.go index b6007b44cb..7ad1cb659a 100644 --- a/params/config.go +++ b/params/config.go @@ -539,11 +539,16 @@ func (c *ChainConfig) IsFenix(num *big.Int) bool { return isForked(c.FenixBlock, num) } -// IsConsortiumV2 returns whether the num is equals to or larger than the Fenix fork block. +// IsConsortiumV2 returns whether the num is equals to or larger than the consortiumV2 fork block. func (c *ChainConfig) IsConsortiumV2(num *big.Int) bool { return isForked(c.ConsortiumV2Block, num) } +// IsOnConsortiumV2 returns whether the num is equals to the consortiumV2 fork block. +func (c *ChainConfig) IsOnConsortiumV2(num *big.Int) bool { + return configNumEqual(c.ConsortiumV2Block, num) +} + // CheckCompatible checks whether scheduled fork transitions have been imported // with a mismatching chain configuration. func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64) *ConfigCompatError { From 11c94a26ee775853111beef2565467f646ce2452 Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Fri, 12 Aug 2022 14:45:02 +0700 Subject: [PATCH 05/52] [RON-161] feat: implement function to interacting with smart contract (#94) * feat(consortiumV2): implement function to interacting with smart contract directly * fix: missing new parameters * fix: missing new parameters * fix: invalid check consortium config nil * fix: use signer hash instead of hash method --- consensus/consensus.go | 4 + consensus/consortium/main.go | 37 ++-- consensus/consortium/v2/abi.go | 5 + consensus/consortium/v2/consortium.go | 58 ++++-- consensus/consortium/v2/contract.go | 284 ++++++++++++++++++++++++++ eth/backend.go | 7 +- eth/ethconfig/config.go | 5 +- les/client.go | 2 +- proxy/server.go | 3 +- 9 files changed, 366 insertions(+), 39 deletions(-) create mode 100644 consensus/consortium/v2/abi.go create mode 100644 consensus/consortium/v2/contract.go diff --git a/consensus/consensus.go b/consensus/consensus.go index 4d6bfad741..f3b3b04c44 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -28,6 +28,10 @@ import ( "github.com/ethereum/go-ethereum/rpc" ) +var ( + SystemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE") +) + // ChainHeaderReader defines a small collection of methods needed to access the local // blockchain during header verification. type ChainHeaderReader interface { diff --git a/consensus/consortium/main.go b/consensus/consortium/main.go index 60e1852210..c22a51b715 100644 --- a/consensus/consortium/main.go +++ b/consensus/consortium/main.go @@ -9,28 +9,29 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" "math/big" ) type Consortium struct { - v1 *v1.Consortium - v2 *v2.Consortium - isConsortiumV2 func(num *big.Int) bool + chainConfig *params.ChainConfig + v1 *v1.Consortium + v2 *v2.Consortium } // New creates a Consortium proof-of-stake consensus engine with the initial // signers set to the ones provided by the user. -func New(config *params.ChainConfig, db ethdb.Database) *Consortium { +func New(chainConfig *params.ChainConfig, db ethdb.Database, ee *ethapi.PublicBlockChainAPI, genesisHash common.Hash) *Consortium { // Set any missing consensus parameters to their defaults - consortiumV1 := v1.New(config.Consortium, db) - consortiumV2 := v2.New(config.Consortium, db) + consortiumV1 := v1.New(chainConfig.Consortium, db) + consortiumV2 := v2.New(chainConfig, db, ee, genesisHash) return &Consortium{ - v1: consortiumV1, - v2: consortiumV2, - isConsortiumV2: config.IsConsortiumV2, + chainConfig: chainConfig, + v1: consortiumV1, + v2: consortiumV2, } } @@ -41,7 +42,7 @@ func (c *Consortium) Author(header *types.Header) (common.Address, error) { } func (c *Consortium) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { - if chain.Config().IsConsortiumV2(header.Number) { + if c.chainConfig.IsConsortiumV2(header.Number) { return c.v2.VerifyHeader(chain, header, seal) } @@ -55,7 +56,7 @@ func (c *Consortium) VerifyHeaders(chain consensus.ChainHeaderReader, headers [] go func() { for i, header := range headers { var err error - if c.isConsortiumV2(header.Number) { + if c.chainConfig.IsConsortiumV2(header.Number) { err = c.v2.VerifyHeaderAndParents(chain, header, headers[:i]) } else { err = c.v1.VerifyHeaderAndParents(chain, header, headers[:i]) @@ -73,7 +74,7 @@ func (c *Consortium) VerifyHeaders(chain consensus.ChainHeaderReader, headers [] } func (c *Consortium) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { - if c.isConsortiumV2(block.Header().Number) { + if c.chainConfig.IsConsortiumV2(block.Header().Number) { return c.v2.VerifyUncles(chain, block) } @@ -81,7 +82,7 @@ func (c *Consortium) VerifyUncles(chain consensus.ChainReader, block *types.Bloc } func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { - if c.isConsortiumV2(header.Number) { + if c.chainConfig.IsConsortiumV2(header.Number) { return c.v2.Prepare(chain, header) } @@ -89,7 +90,7 @@ func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.He } func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) { - if c.isConsortiumV2(header.Number) { + if c.chainConfig.IsConsortiumV2(header.Number) { c.v2.Finalize(chain, header, state, txs, uncles) } else { c.v1.Finalize(chain, header, state, txs, uncles) @@ -97,7 +98,7 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H } func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { - if c.isConsortiumV2(header.Number) { + if c.chainConfig.IsConsortiumV2(header.Number) { return c.v2.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts) } @@ -105,7 +106,7 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head } func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { - if c.isConsortiumV2(block.Header().Number) { + if c.chainConfig.IsConsortiumV2(block.Header().Number) { return c.v2.Seal(chain, block, results, stop) } @@ -113,7 +114,7 @@ func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, } func (c *Consortium) SealHash(header *types.Header) common.Hash { - if c.isConsortiumV2(header.Number) { + if c.chainConfig.IsConsortiumV2(header.Number) { return c.v2.SealHash(header) } @@ -139,7 +140,7 @@ func (c *Consortium) APIs(chain consensus.ChainHeaderReader) []rpc.API { } func (c *Consortium) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { - if c.isConsortiumV2(parent.Number) { + if c.chainConfig.IsConsortiumV2(parent.Number) { return c.v2.CalcDifficulty(chain, time, parent) } diff --git a/consensus/consortium/v2/abi.go b/consensus/consortium/v2/abi.go new file mode 100644 index 0000000000..75198df70d --- /dev/null +++ b/consensus/consortium/v2/abi.go @@ -0,0 +1,5 @@ +package v2 + +const validatorSetABI = `` + +const slashABI = `` diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index 95d813af8f..4332d0aa0a 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -1,6 +1,8 @@ package v2 import ( + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/consensus" @@ -9,10 +11,12 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" lru "github.com/hashicorp/golang-lru" "math/big" + "strings" "sync" "time" ) @@ -39,36 +43,58 @@ var ( diffNoTurn = big.NewInt(3) // Block difficulty for out-of-turn signatures ) +type SignerTxFn func(accounts.Account, *types.Transaction, *big.Int) (*types.Transaction, error) + type Consortium struct { - config *params.ConsortiumConfig // Consensus engine configuration parameters - db ethdb.Database // Database to store and retrieve snapshot checkpoints + chainConfig *params.ChainConfig + config *params.ConsortiumConfig // Consensus engine configuration parameters + genesisHash common.Hash + db ethdb.Database // Database to store and retrieve snapshot checkpoints recents *lru.ARCCache // Snapshots for recent block to speed up reorgs signatures *lru.ARCCache // Signatures of recent blocks to speed up mining - proposals map[common.Address]bool // Current list of proposals we are pushing + val common.Address // Ethereum address of the signing key + signer types.Signer + signFn consortiumCommon.SignerFn // Signer function to authorize hashes with + signTxFn SignerTxFn + + lock sync.RWMutex // Protects the signer fields - signer common.Address // Ethereum address of the signing key - signFn consortiumCommon.SignerFn // Signer function to authorize hashes with - lock sync.RWMutex // Protects the signer fields + ethAPI *ethapi.PublicBlockChainAPI + validatorSetABI abi.ABI + slashABI abi.ABI } -func New(config *params.ConsortiumConfig, db ethdb.Database) *Consortium { - // Set any missing consensus parameters to their defaults - conf := *config - if conf.Epoch == 0 { - conf.Epoch = epochLength +func New( + chainConfig *params.ChainConfig, + db ethdb.Database, + ethAPI *ethapi.PublicBlockChainAPI, + genesisHash common.Hash, +) *Consortium { + consortiumConfig := chainConfig.Consortium + + if consortiumConfig != nil && consortiumConfig.Epoch == 0 { + consortiumConfig.Epoch = epochLength } + // Allocate the snapshot caches and create the engine recents, _ := lru.NewARC(inmemorySnapshots) signatures, _ := lru.NewARC(inmemorySignatures) + vABI, _ := abi.JSON(strings.NewReader(validatorSetABI)) + sABI, _ := abi.JSON(strings.NewReader(slashABI)) return &Consortium{ - config: &conf, - db: db, - recents: recents, - signatures: signatures, - proposals: make(map[common.Address]bool), + chainConfig: chainConfig, + config: consortiumConfig, + genesisHash: genesisHash, + db: db, + ethAPI: ethAPI, + recents: recents, + signatures: signatures, + validatorSetABI: vABI, + slashABI: sABI, + signer: types.NewEIP155Signer(chainConfig.ChainID), } } diff --git a/consensus/consortium/v2/contract.go b/consensus/consortium/v2/contract.go new file mode 100644 index 0000000000..1b85c5fb8f --- /dev/null +++ b/consensus/consortium/v2/contract.go @@ -0,0 +1,284 @@ +package v2 + +import ( + "bytes" + "context" + "encoding/hex" + "errors" + "fmt" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/systemcontracts" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rpc" + "math" + "math/big" +) + +// Interaction with contract/account +func (c *Consortium) getCurrentValidators(blockHash common.Hash, blockNumber *big.Int) ([]common.Address, error) { + blockNr := rpc.BlockNumberOrHashWithHash(blockHash, false) + method := "getValidators" + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() // cancel when we are finished consuming integers + + data, err := c.validatorSetABI.Pack(method) + if err != nil { + log.Error("Unable to pack tx for getValidators", "error", err) + return nil, err + } + + // call + msgData := (hexutil.Bytes)(data) + toAddress := common.HexToAddress(systemcontracts.ValidatorContract) + gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2)) + result, err := c.ethAPI.Call(ctx, ethapi.TransactionArgs{ + Gas: &gas, + To: &toAddress, + Data: &msgData, + }, blockNr, nil) + if err != nil { + return nil, err + } + + var ( + ret0 = new([]common.Address) + ) + out := ret0 + + if err := c.validatorSetABI.UnpackIntoInterface(out, method, result); err != nil { + return nil, err + } + + valz := make([]common.Address, len(*ret0)) + for i, a := range *ret0 { + valz[i] = a + } + return valz, nil +} + +// slash spoiled validators +func (c *Consortium) distributeIncoming( + val common.Address, + state *state.StateDB, + header *types.Header, + chain core.ChainContext, + txs *[]*types.Transaction, + receipts *[]*types.Receipt, + receivedTxs *[]*types.Transaction, + usedGas *uint64, + mining bool, +) error { + coinbase := header.Coinbase + balance := state.GetBalance(consensus.SystemAddress) + if balance.Cmp(common.Big0) <= 0 { + return nil + } + state.SetBalance(consensus.SystemAddress, big.NewInt(0)) + state.AddBalance(coinbase, balance) + + log.Trace("distribute to validator contract", "block hash", header.Hash(), "amount", balance) + return c.distributeToValidator(balance, val, state, header, chain, txs, receipts, receivedTxs, usedGas, mining) +} + +func (c *Consortium) initContract( + state *state.StateDB, + header *types.Header, + chain core.ChainContext, + txs *[]*types.Transaction, + receipts *[]*types.Receipt, + receivedTxs *[]*types.Transaction, + usedGas *uint64, + mining bool, +) error { + // method + method := "init" + // contracts + contracts := []string{ + systemcontracts.ValidatorContract, + systemcontracts.SlashContract, + } + // get packed data + data, err := c.validatorSetABI.Pack(method) + if err != nil { + log.Error("Unable to pack tx for init validator set", "error", err) + return err + } + for _, contract := range contracts { + msg := c.getSystemMessage(header.Coinbase, common.HexToAddress(contract), data, common.Big0) + // apply message + log.Trace("init contract", "block hash", header.Hash(), "contract", contract) + err = c.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining) + if err != nil { + return err + } + } + return nil +} + +// slash spoiled validators +func (c *Consortium) distributeToValidator( + amount *big.Int, + validator common.Address, + state *state.StateDB, + header *types.Header, + chain core.ChainContext, + txs *[]*types.Transaction, + receipts *[]*types.Receipt, + receivedTxs *[]*types.Transaction, + usedGas *uint64, + mining bool, +) error { + // method + method := "deposit" + + // get packed data + data, err := c.validatorSetABI.Pack(method, + validator, + ) + if err != nil { + log.Error("Unable to pack tx for deposit", "error", err) + return err + } + // get system message + msg := c.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.ValidatorContract), data, amount) + // apply message + return c.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining) +} + +func (c *Consortium) getSystemMessage(from, toAddress common.Address, data []byte, value *big.Int) callmsg { + return callmsg{ + ethereum.CallMsg{ + From: from, + Gas: math.MaxUint64 / 2, + GasPrice: big.NewInt(0), + Value: value, + To: &toAddress, + Data: data, + }, + } +} + +func (c *Consortium) applyTransaction( + msg callmsg, + state *state.StateDB, + header *types.Header, + chainContext core.ChainContext, + txs *[]*types.Transaction, + receipts *[]*types.Receipt, + receivedTxs *[]*types.Transaction, + usedGas *uint64, + mining bool, +) (err error) { + nonce := state.GetNonce(msg.From()) + expectedTx := types.NewTransaction(nonce, *msg.To(), msg.Value(), msg.Gas(), msg.GasPrice(), msg.Data()) + expectedHash := c.signer.Hash(expectedTx) + + if msg.From() == c.val && mining { + expectedTx, err = c.signTxFn(accounts.Account{Address: msg.From()}, expectedTx, c.chainConfig.ChainID) + if err != nil { + return err + } + } else { + if receivedTxs == nil || len(*receivedTxs) == 0 || (*receivedTxs)[0] == nil { + return errors.New("supposed to get a actual transaction, but get none") + } + actualTx := (*receivedTxs)[0] + if !bytes.Equal(c.signer.Hash(actualTx).Bytes(), expectedHash.Bytes()) { + return fmt.Errorf("expected tx hash %v, get %v, nonce %d, to %s, value %s, gas %d, gasPrice %s, data %s", expectedHash.String(), actualTx.Hash().String(), + expectedTx.Nonce(), + expectedTx.To().String(), + expectedTx.Value().String(), + expectedTx.Gas(), + expectedTx.GasPrice().String(), + hex.EncodeToString(expectedTx.Data()), + ) + } + expectedTx = actualTx + // move to next + *receivedTxs = (*receivedTxs)[1:] + } + state.Prepare(expectedTx.Hash(), len(*txs)) + gasUsed, err := applyMessage(msg, state, header, c.chainConfig, chainContext) + if err != nil { + return err + } + *txs = append(*txs, expectedTx) + var root []byte + if c.chainConfig.IsByzantium(header.Number) { + state.Finalise(true) + } else { + root = state.IntermediateRoot(c.chainConfig.IsEIP158(header.Number)).Bytes() + } + *usedGas += gasUsed + receipt := types.NewReceipt(root, false, *usedGas) + receipt.TxHash = expectedTx.Hash() + receipt.GasUsed = gasUsed + + // Set the receipt logs and create a bloom for filtering + receipt.Logs = state.GetLogs(expectedTx.Hash(), header.Hash()) + receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) + receipt.BlockHash = header.Hash() + receipt.BlockNumber = header.Number + receipt.TransactionIndex = uint(state.TxIndex()) + *receipts = append(*receipts, receipt) + state.SetNonce(msg.From(), nonce+1) + return nil +} + +func applyMessage( + msg callmsg, + state *state.StateDB, + header *types.Header, + chainConfig *params.ChainConfig, + chainContext core.ChainContext, +) (uint64, error) { + // Create a new context to be used in the EVM environment + context := core.NewEVMBlockContext(header, chainContext, nil) + // Create a new environment which holds all relevant information + // about the transaction and calling mechanisms. + vmenv := vm.NewEVM(context, vm.TxContext{Origin: msg.From(), GasPrice: big.NewInt(0)}, state, chainConfig, vm.Config{}) + // Apply the transaction to the current state (included in the env) + ret, returnGas, err := vmenv.Call( + vm.AccountRef(msg.From()), + *msg.To(), + msg.Data(), + msg.Gas(), + msg.Value(), + ) + if err != nil { + log.Error("apply message failed", "msg", string(ret), "err", err) + } + return msg.Gas() - returnGas, err +} + +// callmsg implements core.Message to allow passing it as a transaction simulator. +type callmsg struct { + ethereum.CallMsg +} + +func (m callmsg) From() common.Address { return m.CallMsg.From } + +func (m callmsg) Nonce() uint64 { return 0 } + +func (m callmsg) CheckNonce() bool { return false } + +func (m callmsg) To() *common.Address { return m.CallMsg.To } + +func (m callmsg) GasPrice() *big.Int { return m.CallMsg.GasPrice } + +func (m callmsg) Gas() uint64 { return m.CallMsg.Gas } + +func (m callmsg) Value() *big.Int { return m.CallMsg.Value } + +func (m callmsg) Data() []byte { return m.CallMsg.Data } diff --git a/eth/backend.go b/eth/backend.go index 36b8ffd7df..ff492e0d0b 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -148,7 +148,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { chainDb: chainDb, eventMux: stack.EventMux(), accountManager: stack.AccountManager(), - engine: ethconfig.CreateConsensusEngine(stack, chainConfig, ðashConfig, config.Miner.Notify, config.Miner.Noverify, chainDb), closeBloomHandler: make(chan struct{}), networkID: config.NetworkId, gasPrice: config.Miner.GasPrice, @@ -157,6 +156,12 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { bloomIndexer: core.NewBloomIndexer(chainDb, params.BloomBitsBlocks, params.BloomConfirms), p2pServer: stack.Server(), } + eth.APIBackend = &EthAPIBackend{stack.Config().ExtRPCEnabled(), stack.Config().AllowUnprotectedTxs, eth, nil} + if eth.APIBackend.allowUnprotectedTxs { + log.Info("Unprotected transactions allowed") + } + ethAPI := ethapi.NewPublicBlockChainAPI(eth.APIBackend) + eth.engine = ethconfig.CreateConsensusEngine(stack, chainConfig, ðashConfig, config.Miner.Notify, config.Miner.Noverify, chainDb, ethAPI, genesisHash) bcVersion := rawdb.ReadDatabaseVersion(chainDb) var dbVer = "" diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index ca1a698899..3a93763d6f 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -19,6 +19,7 @@ package ethconfig import ( "github.com/ethereum/go-ethereum/consensus/consortium" + "github.com/ethereum/go-ethereum/internal/ethapi" "math/big" "os" "os/user" @@ -208,13 +209,13 @@ type Config struct { } // CreateConsensusEngine creates a consensus engine for the given chain configuration. -func CreateConsensusEngine(stack *node.Node, chainConfig *params.ChainConfig, config *ethash.Config, notify []string, noverify bool, db ethdb.Database) consensus.Engine { +func CreateConsensusEngine(stack *node.Node, chainConfig *params.ChainConfig, config *ethash.Config, notify []string, noverify bool, db ethdb.Database, ee *ethapi.PublicBlockChainAPI, genesisHash common.Hash) consensus.Engine { // If proof-of-authority is requested, set it up if chainConfig.Clique != nil { return clique.New(chainConfig.Clique, db) } if chainConfig.Consortium != nil { - return consortium.New(chainConfig, db) + return consortium.New(chainConfig, db, ee, genesisHash) } // Otherwise assume proof-of-work switch config.PowMode { diff --git a/les/client.go b/les/client.go index 5dc3433e40..22ad5bfc82 100644 --- a/les/client.go +++ b/les/client.go @@ -109,7 +109,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*LightEthereum, error) { eventMux: stack.EventMux(), reqDist: newRequestDistributor(peers, &mclock.System{}), accountManager: stack.AccountManager(), - engine: ethconfig.CreateConsensusEngine(stack, chainConfig, &config.Ethash, nil, false, chainDb), + engine: ethconfig.CreateConsensusEngine(stack, chainConfig, &config.Ethash, nil, false, chainDb, nil, genesisHash), bloomRequests: make(chan chan *bloombits.Retrieval), bloomIndexer: core.NewBloomIndexer(chainDb, params.BloomBitsBlocksClient, params.HelperTrieConfirmations), p2pServer: stack.Server(), diff --git a/proxy/server.go b/proxy/server.go index fb85a4632a..d2d4a79d29 100644 --- a/proxy/server.go +++ b/proxy/server.go @@ -2,6 +2,7 @@ package proxy import ( "errors" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus/consortium" "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/internal/ethapi" @@ -59,7 +60,7 @@ func NewServer(config *Config, ethConfig *ethconfig.Config, nodeConfig *node.Con } func (s *Server) Start() { - engine := consortium.New(¶ms.ChainConfig{}, s.backend.db) + engine := consortium.New(¶ms.ChainConfig{}, s.backend.db, nil, common.Hash{}) var apis = []rpc.API{ { Namespace: "eth", From 7a4df0a2a488608ae4981d50b1bef3a3d05bbac1 Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Mon, 15 Aug 2022 15:00:14 +0700 Subject: [PATCH 06/52] chore: update FinalizeAndAssemble method in Engine interface (#96) --- consensus/clique/clique.go | 14 +++-- consensus/consensus.go | 18 ++++++- consensus/consortium/main.go | 17 ++++-- consensus/consortium/v1/consortium.go | 12 ++++- consensus/consortium/v2/consortium.go | 77 +++++++++++++++++++++++++-- consensus/consortium/v2/snapshot.go | 31 +++++++++++ consensus/ethash/consensus.go | 13 +++-- core/state_processor.go | 21 ++++++-- proxy/backend.go | 8 ++- 9 files changed, 188 insertions(+), 23 deletions(-) diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index 38597e1526..fc690e3b42 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -562,17 +562,21 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header // Finalize implements consensus.Engine, ensuring no uncles are set, nor block // rewards given. -func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) { +func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs *[]*types.Transaction, + uncles []*types.Header, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction, usedGas *uint64) error { // No block rewards in PoA, so the state remains as is and uncles are dropped header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) header.UncleHash = types.CalcUncleHash(nil) + + return nil } // FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set, // nor block rewards given, and returns the final block. -func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { +func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, + uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { // Finalize block - c.Finalize(chain, header, state, txs, uncles) + c.Finalize(chain, header, state, &txs, uncles, nil, nil, nil) // Assemble and return the final block for sealing return types.NewBlock(header, txs, nil, receipts, trie.NewStackTrie(nil)), nil @@ -588,6 +592,10 @@ func (c *Clique) Authorize(signer common.Address, signFn SignerFn) { c.signFn = signFn } +func (c *Clique) Delay(chain consensus.ChainReader, header *types.Header) *time.Duration { + return nil +} + // Seal implements consensus.Engine, attempting to create a sealed block using // the local signing credentials. func (c *Clique) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { diff --git a/consensus/consensus.go b/consensus/consensus.go index f3b3b04c44..88f782781e 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -20,6 +20,7 @@ package consensus import ( "github.com/ethereum/go-ethereum/ethdb" "math/big" + "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" @@ -97,8 +98,8 @@ type Engine interface { // // Note: The block header and state database might be updated to reflect any // consensus rules that happen at finalization (e.g. block rewards). - Finalize(chain ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, - uncles []*types.Header) + Finalize(chain ChainHeaderReader, header *types.Header, state *state.StateDB, txs *[]*types.Transaction, + uncles []*types.Header, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction, usedGas *uint64) error // FinalizeAndAssemble runs any post-transaction state modifications (e.g. block // rewards) and assembles the final block. @@ -125,6 +126,9 @@ type Engine interface { // APIs returns the RPC APIs this consensus engine provides. APIs(chain ChainHeaderReader) []rpc.API + // Delay returns the max duration the miner can commit txs + Delay(chain ChainReader, header *types.Header) *time.Duration + // Close terminates any background threads maintained by the consensus engine. Close() error } @@ -136,3 +140,13 @@ type PoW interface { // Hashrate returns the current mining hashrate of a PoW consensus engine. Hashrate() float64 } + +type PoSA interface { + Engine + + IsSystemTransaction(tx *types.Transaction, header *types.Header) (bool, error) + IsSystemContract(to *common.Address) bool + EnoughDistance(chain ChainReader, header *types.Header) bool + IsLocalBlock(header *types.Header) bool + AllowLightProcess(chain ChainReader, currentHeader *types.Header) bool +} diff --git a/consensus/consortium/main.go b/consensus/consortium/main.go index c22a51b715..5ac0870238 100644 --- a/consensus/consortium/main.go +++ b/consensus/consortium/main.go @@ -13,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" "math/big" + "time" ) type Consortium struct { @@ -89,15 +90,17 @@ func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.He return c.v1.Prepare(chain, header) } -func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) { +func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs *[]*types.Transaction, + uncles []*types.Header, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction, usedGas *uint64) error { if c.chainConfig.IsConsortiumV2(header.Number) { - c.v2.Finalize(chain, header, state, txs, uncles) - } else { - c.v1.Finalize(chain, header, state, txs, uncles) + return c.v2.Finalize(chain, header, state, txs, uncles, receipts, systemTxs, usedGas) } + + return c.v1.Finalize(chain, header, state, txs, uncles, receipts, systemTxs, usedGas) } -func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { +func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, + txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { if c.chainConfig.IsConsortiumV2(header.Number) { return c.v2.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts) } @@ -105,6 +108,10 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head return c.v1.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts) } +func (c *Consortium) Delay(chain consensus.ChainReader, header *types.Header) *time.Duration { + return nil +} + func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { if c.chainConfig.IsConsortiumV2(block.Header().Number) { return c.v2.Seal(chain, block, results, stop) diff --git a/consensus/consortium/v1/consortium.go b/consensus/consortium/v1/consortium.go index 5c2b6299e5..8b4a1be329 100644 --- a/consensus/consortium/v1/consortium.go +++ b/consensus/consortium/v1/consortium.go @@ -512,15 +512,19 @@ func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.He // Finalize implements consensus.Engine, ensuring no uncles are set, nor block // rewards given. -func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) { +func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs *[]*types.Transaction, + uncles []*types.Header, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction, usedGas *uint64) error { // No block rewards in PoA, so the state remains as is and uncles are dropped header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) header.UncleHash = types.CalcUncleHash(nil) + + return nil } // FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set, // nor block rewards given, and returns the final block. -func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { +func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, + uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { // No block rewards in PoA, so the state remains as is and uncles are dropped header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) header.UncleHash = types.CalcUncleHash(nil) @@ -539,6 +543,10 @@ func (c *Consortium) Authorize(signer common.Address, signFn consortiumCommon.Si c.signFn = signFn } +func (c *Consortium) Delay(chain consensus.ChainReader, header *types.Header) *time.Duration { + return nil +} + // Seal implements consensus.Engine, attempting to create a sealed block using // the local signing credentials. func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index 4332d0aa0a..0936ef4ddc 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -1,6 +1,7 @@ package v2 import ( + "errors" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" @@ -8,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/consensus" consortiumCommon "github.com/ethereum/go-ethereum/consensus/consortium/common" "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/systemcontracts" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" @@ -43,8 +45,22 @@ var ( diffNoTurn = big.NewInt(3) // Block difficulty for out-of-turn signatures ) +var ( + // 100 native token + maxSystemBalance = new(big.Int).Mul(big.NewInt(100), big.NewInt(params.Ether)) + + systemContracts = map[common.Address]bool{ + common.HexToAddress(systemcontracts.ValidatorContract): true, + common.HexToAddress(systemcontracts.SlashContract): true, + } +) + type SignerTxFn func(accounts.Account, *types.Transaction, *big.Int) (*types.Transaction, error) +func isToSystemContract(to common.Address) bool { + return systemContracts[to] +} + type Consortium struct { chainConfig *params.ChainConfig config *params.ConsortiumConfig // Consensus engine configuration parameters @@ -98,6 +114,51 @@ func New( } } +func (c *Consortium) IsSystemTransaction(tx *types.Transaction, header *types.Header) (bool, error) { + // deploy a contract + if tx.To() == nil { + return false, nil + } + sender, err := types.Sender(c.signer, tx) + if err != nil { + return false, errors.New("UnAuthorized transaction") + } + if sender == header.Coinbase && isToSystemContract(*tx.To()) && tx.GasPrice().Cmp(big.NewInt(0)) == 0 { + return true, nil + } + return false, nil +} + +func (c *Consortium) IsSystemContract(to *common.Address) bool { + if to == nil { + return false + } + return isToSystemContract(*to) +} + +func (c *Consortium) EnoughDistance(chain consensus.ChainReader, header *types.Header) bool { + snap, err := c.snapshot(chain, header.Number.Uint64()-1, header.ParentHash, nil) + if err != nil { + return true + } + return snap.enoughDistance(c.val, header) +} + +func (c *Consortium) IsLocalBlock(header *types.Header) bool { + return c.val == header.Coinbase +} + +func (c *Consortium) AllowLightProcess(chain consensus.ChainReader, currentHeader *types.Header) bool { + snap, err := c.snapshot(chain, currentHeader.Number.Uint64()-1, currentHeader.ParentHash, nil) + if err != nil { + return true + } + + idx := snap.indexOfVal(c.val) + // validator is not allowed to diff sync + return idx < 0 +} + func (c *Consortium) Author(header *types.Header) (common.Address, error) { return common.Address{}, nil } @@ -117,6 +178,10 @@ func (c *Consortium) VerifyHeaderAndParents(chain consensus.ChainHeaderReader, h return nil } +func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64, hash common.Hash, parents []*types.Header) (*Snapshot, error) { + return nil, nil +} + func (c *Consortium) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { return nil } @@ -125,14 +190,20 @@ func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.He return nil } -func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) { - +func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs *[]*types.Transaction, + uncles []*types.Header, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction, usedGas *uint64) error { + return nil } -func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { +func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, + txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { return nil, nil } +func (c *Consortium) Delay(chain consensus.ChainReader, header *types.Header) *time.Duration { + return nil +} + func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { return nil } diff --git a/consensus/consortium/v2/snapshot.go b/consensus/consortium/v2/snapshot.go index 960fc00f44..f76c4f1a41 100644 --- a/consensus/consortium/v2/snapshot.go +++ b/consensus/consortium/v2/snapshot.go @@ -1,17 +1,34 @@ package v2 import ( + "bytes" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/params" lru "github.com/hashicorp/golang-lru" ) type Snapshot struct { + config *params.ConsortiumConfig // Consensus engine parameters to fine tune behavior + ethAPI *ethapi.PublicBlockChainAPI + sigCache *lru.ARCCache // Cache of recent block signatures to speed up ecrecover + + Number uint64 `json:"number"` // Block number where the snapshot was created + Hash common.Hash `json:"hash"` // Block hash where the snapshot was created + Validators map[common.Address]struct{} `json:"validators"` // Set of authorized validators at this moment + Recents map[uint64]common.Address `json:"recents"` // Set of recent validators for spam protections } +// validatorsAscending implements the sort interface to allow sorting a list of addresses +type validatorsAscending []common.Address + +func (s validatorsAscending) Len() int { return len(s) } +func (s validatorsAscending) Less(i, j int) bool { return bytes.Compare(s[i][:], s[j][:]) < 0 } +func (s validatorsAscending) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + func newSnapshot(config *params.ConsortiumConfig, sigcache *lru.ARCCache, number uint64, hash common.Hash, signers []common.Address) *Snapshot { snap := &Snapshot{} @@ -33,3 +50,17 @@ func (s *Snapshot) copy() *Snapshot { func (s *Snapshot) apply(chain consensus.ChainHeaderReader, c *Consortium, headers []*types.Header, parents []*types.Header) (*Snapshot, error) { return nil, nil } + +// validators retrieves the list of validators in ascending order. +func (s *Snapshot) validators() []common.Address { + validators := make([]common.Address, 0, len(s.Validators)) + return validators +} + +func (s *Snapshot) enoughDistance(validator common.Address, header *types.Header) bool { + return false +} + +func (s *Snapshot) indexOfVal(validator common.Address) int { + return -1 +} diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index 7fa427f68b..89220d3685 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -591,22 +591,29 @@ func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.H // Finalize implements consensus.Engine, accumulating the block and uncle rewards, // setting the final state on the header -func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) { +func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs *[]*types.Transaction, + uncles []*types.Header, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction, usedGas *uint64) error { // Accumulate any block and uncle rewards and commit the final state root accumulateRewards(chain.Config(), state, header, uncles) header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) + return nil } // FinalizeAndAssemble implements consensus.Engine, accumulating the block and // uncle rewards, setting the final state and assembling the block. -func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { +func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, + txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { // Finalize block - ethash.Finalize(chain, header, state, txs, uncles) + ethash.Finalize(chain, header, state, &txs, uncles, nil, nil, nil) // Header seems complete, assemble into a block and return return types.NewBlock(header, txs, uncles, receipts, trie.NewStackTrie(nil)), nil } +func (ethash *Ethash) Delay(chain consensus.ChainReader, header *types.Header) *time.Duration { + return nil +} + // SealHash returns the hash of a block prior to it being sealed. func (ethash *Ethash) SealHash(header *types.Header) (hash common.Hash) { hasher := sha3.NewLegacyKeccak256() diff --git a/core/state_processor.go b/core/state_processor.go index 2971f86b11..b3dbbe2705 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -59,7 +59,6 @@ func NewStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consen // transactions failed to execute due to insufficient gas it will return an error. func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config, publishEvents ...*vm.PublishEvent) (types.Receipts, []*types.Log, uint64, error) { var ( - receipts types.Receipts usedGas = new(uint64) header = block.Header() blockHash = block.Hash() @@ -67,6 +66,8 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg allLogs []*types.Log gp = new(GasPool).AddGas(block.GasLimit()) ) + + var receipts = make([]*types.Receipt, 0) // Mutate the block and state according to any hard-fork specs if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 { misc.ApplyDAOHardFork(statedb) @@ -76,6 +77,12 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg blockContext := NewEVMBlockContext(header, p.bc, nil, publishEvents...) vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg) + + txNum := len(block.Transactions()) + commonTxs := make([]*types.Transaction, 0, txNum) + + systemTxs := make([]*types.Transaction, 0, 2) + // Iterate over and process the individual transactions for i, tx := range block.Transactions() { // set current transaction in block context to each transaction @@ -91,11 +98,19 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg if err != nil { return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) } - receipts = append(receipts, receipt) allLogs = append(allLogs, receipt.Logs...) + + commonTxs = append(commonTxs, tx) + receipts = append(receipts, receipt) } // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) - p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles()) + err := p.engine.Finalize(p.bc, header, statedb, &commonTxs, block.Uncles(), &receipts, &systemTxs, usedGas) + if err != nil { + return receipts, allLogs, *usedGas, err + } + for _, receipt := range receipts { + allLogs = append(allLogs, receipt.Logs...) + } return receipts, allLogs, *usedGas, nil } diff --git a/proxy/backend.go b/proxy/backend.go index c0a8ef7ae6..397ac396cd 100644 --- a/proxy/backend.go +++ b/proxy/backend.go @@ -20,6 +20,7 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb/httpdb" "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" @@ -52,6 +53,7 @@ type backend struct { fgpClient *ethclient.Client chainConfig *params.ChainConfig safeBlockRange uint + genesisHash common.Hash } func (b *backend) Config() *params.ChainConfig { @@ -115,7 +117,7 @@ func NewBackend(cfg *Config, ethConfig *ethconfig.Config) (*backend, error) { if err != nil { return nil, err } - chainConfig, _, err := core.SetupGenesisBlockWithOverride(db, nil, nil, false) + chainConfig, genesisHash, err := core.SetupGenesisBlockWithOverride(db, nil, nil, false) if err != nil { return nil, err } @@ -127,6 +129,7 @@ func NewBackend(cfg *Config, ethConfig *ethconfig.Config) (*backend, error) { currentBlock: &atomic.Value{}, safeBlockRange: defaultSafeBlockRange, stateCache: state.NewDatabaseWithConfig(db, &trie.Config{Cache: 16}), + genesisHash: genesisHash, } if cfg.FreeGasProxy != "" { if b.fgpClient, err = ethclient.Dial(cfg.FreeGasProxy); err != nil { @@ -431,7 +434,8 @@ func (b *backend) ChainConfig() *params.ChainConfig { } func (b *backend) Engine() consensus.Engine { - return consortium.New(b.ChainConfig(), b.db) + ethAPI := ethapi.NewPublicBlockChainAPI(b) + return consortium.New(b.ChainConfig(), b.db, ethAPI, b.genesisHash) } func (b *backend) GetHeader(hash common.Hash, number uint64) *types.Header { From 2c11cbbe2c37a7d189f83758c73f4b66f4fad5e8 Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Tue, 16 Aug 2022 12:00:20 +0700 Subject: [PATCH 07/52] [RON-165] Implement Snapshot methods (#98) * feat: implement Snapshot methods * feat: implement isMajorityFork method * chore: implement isMajorityFork method * fix: update loadSnapshot location * fix: update store location * chore: comment unused method * chore: remove RecentForkHashes property --- consensus/consortium/v2/consortium.go | 94 +++++++++++ consensus/consortium/v2/snapshot.go | 223 ++++++++++++++++++++++++-- 2 files changed, 307 insertions(+), 10 deletions(-) diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index 0936ef4ddc..b5839f064f 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -1,6 +1,7 @@ package v2 import ( + "bytes" "errors" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/abi" @@ -15,8 +16,11 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" lru "github.com/hashicorp/golang-lru" + "golang.org/x/crypto/sha3" + "io" "math/big" "strings" "sync" @@ -28,6 +32,9 @@ const ( inmemorySignatures = 4096 // Number of recent block signatures to keep in memory wiggleTime = 1000 * time.Millisecond // Random delay (per signer) to allow concurrent signers + + nextForkHashSize = 4 // Fixed number of extra-data suffix bytes reserved for nextForkHash. + validatorBytesLength = common.AddressLength ) // Consortium proof-of-authority protocol constants. @@ -55,6 +62,23 @@ var ( } ) +var ( + // errUnauthorizedValidator is returned if a header is signed by a non-authorized entity. + errUnauthorizedValidator = errors.New("unauthorized validator") + + // errOutOfRangeChain is returned if an authorization list is attempted to + // be modified via out-of-range or non-contiguous headers. + errOutOfRangeChain = errors.New("out of range or non-contiguous chain") + + // errBlockHashInconsistent is returned if an authorization list is attempted to + // insert an inconsistent block. + errBlockHashInconsistent = errors.New("the block hash is inconsistent") + + // errRecentlySigned is returned if a header is signed by an authorized entity + // that already signed a header recently, thus is temporarily not allowed to. + errRecentlySigned = errors.New("recently signed") +) + type SignerTxFn func(accounts.Account, *types.Transaction, *big.Int) (*types.Transaction, error) func isToSystemContract(to common.Address) bool { @@ -223,3 +247,73 @@ func (c *Consortium) APIs(chain consensus.ChainHeaderReader) []rpc.API { func (c *Consortium) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { return nil } + +// ecrecover extracts the Ethereum account address from a signed header. +func ecrecover(header *types.Header, sigcache *lru.ARCCache, chainId *big.Int) (common.Address, error) { + // If the signature's already cached, return that + hash := header.Hash() + if address, known := sigcache.Get(hash); known { + return address.(common.Address), nil + } + // Retrieve the signature from the header extra-data + if len(header.Extra) < consortiumCommon.ExtraSeal { + return common.Address{}, consortiumCommon.ErrMissingSignature + } + signature := header.Extra[len(header.Extra)-consortiumCommon.ExtraSeal:] + + // Recover the public key and the Ethereum address + pubkey, err := crypto.Ecrecover(SealHash(header, chainId).Bytes(), signature) + if err != nil { + return common.Address{}, err + } + var signer common.Address + copy(signer[:], crypto.Keccak256(pubkey[1:])[12:]) + + sigcache.Add(hash, signer) + return signer, nil +} + +// SealHash returns the hash of a block prior to it being sealed. +func SealHash(header *types.Header, chainId *big.Int) (hash common.Hash) { + hasher := sha3.NewLegacyKeccak256() + encodeSigHeader(hasher, header, chainId) + hasher.Sum(hash[:0]) + return hash +} + +// consortiumRLP returns the rlp bytes which needs to be signed for the proof-of-authority +// sealing. The RLP to sign consists of the entire header apart from the 65 byte signature +// contained at the end of the extra data. +// +// Note, the method requires the extra data to be at least 65 bytes, otherwise it +// panics. This is done to avoid accidentally using both forms (signature present +// or not), which could be abused to produce different hashes for the same header. +func consortiumRLP(header *types.Header, chainId *big.Int) []byte { + b := new(bytes.Buffer) + encodeSigHeader(b, header, chainId) + return b.Bytes() +} + +func encodeSigHeader(w io.Writer, header *types.Header, chainId *big.Int) { + err := rlp.Encode(w, []interface{}{ + chainId, + header.ParentHash, + header.UncleHash, + header.Coinbase, + header.Root, + header.TxHash, + header.ReceiptHash, + header.Bloom, + header.Difficulty, + header.Number, + header.GasLimit, + header.GasUsed, + header.Time, + header.Extra[:len(header.Extra)-crypto.SignatureLength], // Yes, this will panic if extra is too short + header.MixDigest, + header.Nonce, + }) + if err != nil { + panic("can't encode: " + err.Error()) + } +} diff --git a/consensus/consortium/v2/snapshot.go b/consensus/consortium/v2/snapshot.go index f76c4f1a41..41815369d3 100644 --- a/consensus/consortium/v2/snapshot.go +++ b/consensus/consortium/v2/snapshot.go @@ -2,6 +2,8 @@ package v2 import ( "bytes" + "encoding/json" + "errors" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/core/types" @@ -9,6 +11,8 @@ import ( "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/params" lru "github.com/hashicorp/golang-lru" + "math/big" + "sort" ) type Snapshot struct { @@ -29,38 +33,237 @@ func (s validatorsAscending) Len() int { return len(s) } func (s validatorsAscending) Less(i, j int) bool { return bytes.Compare(s[i][:], s[j][:]) < 0 } func (s validatorsAscending) Swap(i, j int) { s[i], s[j] = s[j], s[i] } -func newSnapshot(config *params.ConsortiumConfig, sigcache *lru.ARCCache, number uint64, hash common.Hash, signers []common.Address) *Snapshot { - snap := &Snapshot{} - +func newSnapshot(config *params.ConsortiumConfig, sigcache *lru.ARCCache, number uint64, hash common.Hash, validators []common.Address, ethAPI *ethapi.PublicBlockChainAPI) *Snapshot { + snap := &Snapshot{ + config: config, + ethAPI: ethAPI, + sigCache: sigcache, + Number: number, + Hash: hash, + Recents: make(map[uint64]common.Address), + Validators: make(map[common.Address]struct{}), + } + for _, v := range validators { + snap.Validators[v] = struct{}{} + } return snap } -func loadSnapshot(config *params.ConsortiumConfig, sigcache *lru.ARCCache, db ethdb.Database, hash common.Hash) (*Snapshot, error) { - return nil, nil +func loadSnapshot(config *params.ConsortiumConfig, sigcache *lru.ARCCache, db ethdb.Database, hash common.Hash, ethAPI *ethapi.PublicBlockChainAPI) (*Snapshot, error) { + blob, err := db.Get(append([]byte("consortium-v2-"), hash[:]...)) + if err != nil { + return nil, err + } + snap := new(Snapshot) + if err := json.Unmarshal(blob, snap); err != nil { + return nil, err + } + snap.config = config + snap.sigCache = sigcache + snap.ethAPI = ethAPI + + return snap, nil } func (s *Snapshot) store(db ethdb.Database) error { - return nil + blob, err := json.Marshal(s) + if err != nil { + return err + } + return db.Put(append([]byte("consortium-v2-"), s.Hash[:]...), blob) } func (s *Snapshot) copy() *Snapshot { - return nil + cpy := &Snapshot{ + config: s.config, + ethAPI: s.ethAPI, + sigCache: s.sigCache, + Number: s.Number, + Hash: s.Hash, + Validators: make(map[common.Address]struct{}), + Recents: make(map[uint64]common.Address), + } + + for v := range s.Validators { + cpy.Validators[v] = struct{}{} + } + for block, v := range s.Recents { + cpy.Recents[block] = v + } + return cpy } -func (s *Snapshot) apply(chain consensus.ChainHeaderReader, c *Consortium, headers []*types.Header, parents []*types.Header) (*Snapshot, error) { - return nil, nil +func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderReader, parents []*types.Header, chainId *big.Int) (*Snapshot, error) { + // Allow passing in no headers for cleaner code + if len(headers) == 0 { + return s, nil + } + // Sanity check that the headers can be applied + for i := 0; i < len(headers)-1; i++ { + if headers[i+1].Number.Uint64() != headers[i].Number.Uint64()+1 { + return nil, errOutOfRangeChain + } + if !bytes.Equal(headers[i+1].ParentHash.Bytes(), headers[i].Hash().Bytes()) { + return nil, errBlockHashInconsistent + } + } + if headers[0].Number.Uint64() != s.Number+1 { + return nil, errOutOfRangeChain + } + if !bytes.Equal(headers[0].ParentHash.Bytes(), s.Hash.Bytes()) { + return nil, errBlockHashInconsistent + } + // Iterate through the headers and create a new snapshot + snap := s.copy() + + for _, header := range headers { + number := header.Number.Uint64() + // Delete the oldest validator from the recent list to allow it signing again + if limit := uint64(len(snap.Validators)/2 + 1); number >= limit { + delete(snap.Recents, number-limit) + } + // Resolve the authorization key and check against signers + validator, err := ecrecover(header, s.sigCache, chainId) + if err != nil { + return nil, err + } + if _, ok := snap.Validators[validator]; !ok { + return nil, errUnauthorizedValidator + } + for _, recent := range snap.Recents { + if recent == validator { + return nil, errRecentlySigned + } + } + snap.Recents[number] = validator + // change validator set + if number > 0 && number%s.config.Epoch == uint64(len(snap.Validators)/2) { + checkpointHeader := FindAncientHeader(header, uint64(len(snap.Validators)/2), chain, parents) + if checkpointHeader == nil { + return nil, consensus.ErrUnknownAncestor + } + + validatorBytes := checkpointHeader.Extra[extraVanity : len(checkpointHeader.Extra)-extraSeal] + // get validators from headers and use that for new validator set + newValArr, err := ParseValidators(validatorBytes) + if err != nil { + return nil, err + } + newVals := make(map[common.Address]struct{}, len(newValArr)) + for _, val := range newValArr { + newVals[val] = struct{}{} + } + oldLimit := len(snap.Validators)/2 + 1 + newLimit := len(newVals)/2 + 1 + if newLimit < oldLimit { + for i := 0; i < oldLimit-newLimit; i++ { + delete(snap.Recents, number-uint64(newLimit)-uint64(i)) + } + } + oldLimit = len(snap.Validators) + newLimit = len(newVals) + snap.Validators = newVals + } + } + snap.Number += uint64(len(headers)) + snap.Hash = headers[len(headers)-1].Hash() + return snap, nil } // validators retrieves the list of validators in ascending order. func (s *Snapshot) validators() []common.Address { validators := make([]common.Address, 0, len(s.Validators)) + for v := range s.Validators { + validators = append(validators, v) + } + sort.Sort(validatorsAscending(validators)) return validators } func (s *Snapshot) enoughDistance(validator common.Address, header *types.Header) bool { - return false + idx := s.indexOfVal(validator) + if idx < 0 { + return true + } + validatorNum := int64(len(s.validators())) + if validatorNum == 1 { + return true + } + if validator == header.Coinbase { + return false + } + offset := (int64(s.Number) + 1) % validatorNum + if int64(idx) >= offset { + return int64(idx)-offset >= validatorNum-2 + } else { + return validatorNum+int64(idx)-offset >= validatorNum-2 + } } func (s *Snapshot) indexOfVal(validator common.Address) int { + validators := s.validators() + for idx, val := range validators { + if val == validator { + return idx + } + } return -1 } + +// inturn returns if a validator at a given block height is in-turn or not. +func (s *Snapshot) inturn(validator common.Address) bool { + validators := s.validators() + offset := (s.Number + 1) % uint64(len(validators)) + return validators[offset] == validator +} + +func ParseValidators(validatorsBytes []byte) ([]common.Address, error) { + if len(validatorsBytes)%validatorBytesLength != 0 { + return nil, errors.New("invalid validators bytes") + } + n := len(validatorsBytes) / validatorBytesLength + result := make([]common.Address, n) + for i := 0; i < n; i++ { + address := make([]byte, validatorBytesLength) + copy(address, validatorsBytes[i*validatorBytesLength:(i+1)*validatorBytesLength]) + result[i] = common.BytesToAddress(address) + } + return result, nil +} + +func FindAncientHeader(header *types.Header, ite uint64, chain consensus.ChainHeaderReader, candidateParents []*types.Header) *types.Header { + ancient := header + for i := uint64(1); i <= ite; i++ { + parentHash := ancient.ParentHash + parentHeight := ancient.Number.Uint64() - 1 + found := false + if len(candidateParents) > 0 { + index := sort.Search(len(candidateParents), func(i int) bool { + return candidateParents[i].Number.Uint64() >= parentHeight + }) + if index < len(candidateParents) && candidateParents[index].Number.Uint64() == parentHeight && + candidateParents[index].Hash() == parentHash { + ancient = candidateParents[index] + found = true + } + } + if !found { + ancient = chain.GetHeader(parentHash, parentHeight) + found = true + } + if ancient == nil || !found { + return nil + } + } + return ancient +} + +//func (s *Snapshot) isMajorityFork(forkHash string) bool { +// ally := 0 +// for _, h := range s.RecentForkHashes { +// if h == forkHash { +// ally++ +// } +// } +// return ally > len(s.RecentForkHashes)/2 +//} From 6c366810b73b6180c1c4776bc1695e2edfffd1f8 Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Tue, 16 Aug 2022 15:31:37 +0700 Subject: [PATCH 08/52] feat: implement Consortium v2 verify methods (#99) * feat: implement Consortium v2 verify method * refactor: comment unused check in verifyCascadingFields * refactor: use misc.VerifyGaslimit instead --- consensus/consortium/common/constants.go | 40 +++ consensus/consortium/common/utils.go | 87 ++---- consensus/consortium/v1/consortium.go | 177 +++++------ consensus/consortium/v1/snapshot.go | 3 +- consensus/consortium/v2/consortium.go | 311 ++++++++++++++++++-- consensus/consortium/v2/consortiumv2fork.go | 13 + consensus/consortium/v2/context.go | 21 ++ consensus/consortium/v2/contract.go | 20 ++ consensus/consortium/v2/snapshot.go | 6 + params/protocol_params.go | 7 +- 10 files changed, 505 insertions(+), 180 deletions(-) create mode 100644 consensus/consortium/v2/consortiumv2fork.go create mode 100644 consensus/consortium/v2/context.go diff --git a/consensus/consortium/common/constants.go b/consensus/consortium/common/constants.go index 2c836dfdbd..7f68b57bd8 100644 --- a/consensus/consortium/common/constants.go +++ b/consensus/consortium/common/constants.go @@ -2,9 +2,12 @@ package common import ( "errors" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" ) +const ValidatorBytesLength = common.AddressLength + var ( ExtraSeal = crypto.SignatureLength // Fixed number of extra-data suffix bytes reserved for signer seal ) @@ -13,4 +16,41 @@ var ( // ErrMissingSignature is returned if a block's extra-data section doesn't seem // to contain a 65 byte secp256k1 signature. ErrMissingSignature = errors.New("extra-data 65 byte signature suffix missing") + + // ErrUnknownBlock is returned when the list of signers is requested for a block + // that is not part of the local blockchain. + ErrUnknownBlock = errors.New("unknown block") + + // ErrMissingVanity is returned if a block's extra-data section is shorter than + // 32 bytes, which is required to store the signer vanity. + ErrMissingVanity = errors.New("extra-data 32 byte vanity prefix missing") + + // ErrExtraValidators is returned if non-sprint-end block contain validator data in + // their extra-data fields. + ErrExtraValidators = errors.New("non-sprint-end block contains extra validator list") + + // ErrInvalidSpanValidators is returned if a block contains an + // invalid list of validators (i.e. non divisible by 20 bytes). + ErrInvalidSpanValidators = errors.New("invalid validator list on sprint end block") + + // ErrInvalidMixDigest is returned if a block's mix digest is non-zero. + ErrInvalidMixDigest = errors.New("non-zero mix digest") + + // ErrInvalidUncleHash is returned if a block contains an non-empty uncle list. + ErrInvalidUncleHash = errors.New("non empty uncle hash") + + // ErrInvalidDifficulty is returned if the difficulty of a block neither 1 or 2. + ErrInvalidDifficulty = errors.New("invalid difficulty") + + // ErrInvalidCheckpointSigners is returned if a checkpoint block contains an + // invalid list of signers (i.e. non divisible by 20 bytes). + ErrInvalidCheckpointSigners = errors.New("invalid signer list on checkpoint block") + + // ErrRecentlySigned is returned if a header is signed by an authorized entity + // that already signed a header recently, thus is temporarily not allowed to. + ErrRecentlySigned = errors.New("recently signed") + + // ErrWrongDifficulty is returned if the difficulty of a block doesn't match the + // turn of the signer. + ErrWrongDifficulty = errors.New("wrong difficulty") ) diff --git a/consensus/consortium/common/utils.go b/consensus/consortium/common/utils.go index 5c29edcc0e..d7d5dec16a 100644 --- a/consensus/consortium/common/utils.go +++ b/consensus/consortium/common/utils.go @@ -1,81 +1,30 @@ package common import ( - "bytes" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/rlp" - lru "github.com/hashicorp/golang-lru" - "golang.org/x/crypto/sha3" - "io" ) -// Ecrecover extracts the Ethereum account address from a signed header. -func Ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) { - // If the signature's already cached, return that - hash := header.Hash() - if address, known := sigcache.Get(hash); known { - return address.(common.Address), nil +func ExtractAddressFromBytes(bytes []byte) []common.Address { + if bytes != nil && len(bytes) < common.AddressLength { + return []common.Address{} } - // Retrieve the signature from the header extra-data - if len(header.Extra) < ExtraSeal { - return common.Address{}, ErrMissingSignature + results := make([]common.Address, len(bytes)/common.AddressLength) + for i := 0; i < len(results); i++ { + copy(results[i][:], bytes[i*common.AddressLength:]) } - signature := header.Extra[len(header.Extra)-ExtraSeal:] - - // Recover the public key and the Ethereum address - pubkey, err := crypto.Ecrecover(SealHash(header).Bytes(), signature) - if err != nil { - return common.Address{}, err - } - var signer common.Address - copy(signer[:], crypto.Keccak256(pubkey[1:])[12:]) - - sigcache.Add(hash, signer) - return signer, nil -} - -// SealHash returns the hash of a block prior to it being sealed. -func SealHash(header *types.Header) (hash common.Hash) { - hasher := sha3.NewLegacyKeccak256() - encodeSigHeader(hasher, header) - hasher.Sum(hash[:0]) - return hash -} - -// ConsortiumRLP returns the rlp bytes which needs to be signed for the proof-of-authority -// sealing. The RLP to sign consists of the entire header apart from the 65 byte signature -// contained at the end of the extra data. -// -// Note, the method requires the extra data to be at least 65 bytes, otherwise it -// panics. This is done to avoid accidentally using both forms (signature present -// or not), which could be abused to produce different hashes for the same header. -func ConsortiumRLP(header *types.Header) []byte { - b := new(bytes.Buffer) - encodeSigHeader(b, header) - return b.Bytes() + return results } -func encodeSigHeader(w io.Writer, header *types.Header) { - err := rlp.Encode(w, []interface{}{ - header.ParentHash, - header.UncleHash, - header.Coinbase, - header.Root, - header.TxHash, - header.ReceiptHash, - header.Bloom, - header.Difficulty, - header.Number, - header.GasLimit, - header.GasUsed, - header.Time, - header.Extra[:len(header.Extra)-crypto.SignatureLength], // Yes, this will panic if extra is too short - header.MixDigest, - header.Nonce, - }) - if err != nil { - panic("can't encode: " + err.Error()) +// CompareSignersLists compares 2 signers lists +// return true if they are same elements, otherwise return false +func CompareSignersLists(list1 []common.Address, list2 []common.Address) bool { + if len(list1) != len(list2) { + return false + } + for i := 0; i < len(list1); i++ { + if list1[i].Hex() != list2[i].Hex() { + return false + } } + return true } diff --git a/consensus/consortium/v1/consortium.go b/consensus/consortium/v1/consortium.go index 8b4a1be329..ab2b4c49e1 100644 --- a/consensus/consortium/v1/consortium.go +++ b/consensus/consortium/v1/consortium.go @@ -20,6 +20,10 @@ package v1 import ( "bytes" "errors" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/rlp" + "golang.org/x/crypto/sha3" + "io" "math/big" "math/rand" "sync" @@ -67,57 +71,20 @@ var ( // codebase, inherently breaking if the engine is swapped out. Please put common // error types into the consensus package. var ( - // errUnknownBlock is returned when the list of signers is requested for a block - // that is not part of the local blockchain. - errUnknownBlock = errors.New("unknown block") - - // errInvalidCheckpointBeneficiary is returned if a checkpoint/epoch transition - // block has a beneficiary set to non-zeroes. - errInvalidCheckpointBeneficiary = errors.New("beneficiary in checkpoint block non-zero") - // errInvalidNonce is returned if a nonce value is not 0x00..0 errInvalidNonce = errors.New("nonce not 0x00..0 ") - // errMissingVanity is returned if a block's extra-data section is shorter than - // 32 bytes, which is required to store the signer vanity. - errMissingVanity = errors.New("extra-data 32 byte vanity prefix missing") - // errExtraSigners is returned if non-checkpoint block contain signer data in // their extra-data fields. errExtraSigners = errors.New("non-checkpoint block contains extra signer list") - // errInvalidCheckpointSigners is returned if a checkpoint block contains an - // invalid list of signers (i.e. non divisible by 20 bytes). - errInvalidCheckpointSigners = errors.New("invalid signer list on checkpoint block") - - // errMismatchingCheckpointSigners is returned if a checkpoint block contains a - // list of signers different than the one the local node calculated. - errMismatchingCheckpointSigners = errors.New("mismatching signer list on checkpoint block") - - // errInvalidMixDigest is returned if a block's mix digest is non-zero. - errInvalidMixDigest = errors.New("non-zero mix digest") - - // errInvalidUncleHash is returned if a block contains an non-empty uncle list. - errInvalidUncleHash = errors.New("non empty uncle hash") - - // errInvalidDifficulty is returned if the difficulty of a block neither 1 or 2. - errInvalidDifficulty = errors.New("invalid difficulty") - - // errWrongDifficulty is returned if the difficulty of a block doesn't match the - // turn of the signer. - errWrongDifficulty = errors.New("wrong difficulty") - // ErrInvalidTimestamp is returned if the timestamp of a block is lower than // the previous block's timestamp + the minimum block period. - ErrInvalidTimestamp = errors.New("invalid timestamp") + errInvalidTimestamp = errors.New("invalid timestamp") // errUnauthorizedSigner is returned if a header is signed by a non-authorized entity. errUnauthorizedSigner = errors.New("unauthorized signer") - // errRecentlySigned is returned if a header is signed by an authorized entity - // that already signed a header recently, thus is temporarily not allowed to. - errRecentlySigned = errors.New("recently signed") - // errWrongCoinbase is returned if the coinbase field in header does not match the signer // of that block. errWrongCoinbase = errors.New("wrong coinbase address") @@ -176,7 +143,7 @@ func (c *Consortium) SetGetFenixValidators(fn func() ([]common.Address, error)) // Author implements consensus.Engine, returning the Ethereum address recovered // from the signature in the header's extra-data section. func (c *Consortium) Author(header *types.Header) (common.Address, error) { - return consortiumCommon.Ecrecover(header, c.signatures) + return ecrecover(header, c.signatures) } // VerifyHeader checks whether a header conforms to the consensus rules. @@ -211,7 +178,7 @@ func (c *Consortium) VerifyHeaders(chain consensus.ChainHeaderReader, headers [] // a batch of new headers. func (c *Consortium) VerifyHeaderAndParents(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error { if header.Number == nil { - return errUnknownBlock + return consortiumCommon.ErrUnknownBlock } number := header.Number.Uint64() @@ -225,7 +192,7 @@ func (c *Consortium) VerifyHeaderAndParents(chain consensus.ChainHeaderReader, h } // Check that the extra-data contains both the vanity and signature if len(header.Extra) < extraVanity { - return errMissingVanity + return consortiumCommon.ErrMissingVanity } if len(header.Extra) < extraVanity+consortiumCommon.ExtraSeal { return consortiumCommon.ErrMissingSignature @@ -237,20 +204,20 @@ func (c *Consortium) VerifyHeaderAndParents(chain consensus.ChainHeaderReader, h return errExtraSigners } if checkpoint && signersBytes%common.AddressLength != 0 { - return errInvalidCheckpointSigners + return consortiumCommon.ErrInvalidCheckpointSigners } // Ensure that the mix digest is zero as we don't have fork protection currently if header.MixDigest != (common.Hash{}) { - return errInvalidMixDigest + return consortiumCommon.ErrInvalidMixDigest } // Ensure that the block doesn't contain any uncles which are meaningless in PoA if header.UncleHash != uncleHash { - return errInvalidUncleHash + return consortiumCommon.ErrInvalidUncleHash } // Ensure that the block's difficulty is meaningful (may not be correct at this point) if number > 0 { if header.Difficulty == nil || (header.Difficulty.Cmp(diffInTurn) != 0 && header.Difficulty.Cmp(diffNoTurn) != 0) { - return errInvalidDifficulty + return consortiumCommon.ErrInvalidDifficulty } } // If all checks passed, validate any special fields for hard forks @@ -282,7 +249,7 @@ func (c *Consortium) verifyCascadingFields(chain consensus.ChainHeaderReader, he return consensus.ErrUnknownAncestor } if parent.Time+c.config.Period > header.Time { - return ErrInvalidTimestamp + return errInvalidTimestamp } // If the block is a checkpoint block, verify the signer list @@ -296,31 +263,17 @@ func (c *Consortium) verifyCascadingFields(chain consensus.ChainHeaderReader, he } extraSuffix := len(header.Extra) - consortiumCommon.ExtraSeal - checkpointHeaders := extractAddressFromBytes(header.Extra[extraVanity:extraSuffix]) - validSigners := compareSignersLists(checkpointHeaders, signers) + checkpointHeaders := consortiumCommon.ExtractAddressFromBytes(header.Extra[extraVanity:extraSuffix]) + validSigners := consortiumCommon.CompareSignersLists(checkpointHeaders, signers) if !validSigners { log.Error("signers lists are different in checkpoint header and snapshot", "number", number, "signersHeader", checkpointHeaders, "signers", signers) - return errInvalidCheckpointSigners + return consortiumCommon.ErrInvalidCheckpointSigners } // All basic checks passed, verify the seal and return return c.verifySeal(chain, header, parents) } -// compare 2 signers lists -// return true if they are same elements, otherwise return false -func compareSignersLists(list1 []common.Address, list2 []common.Address) bool { - if len(list1) != len(list2) { - return false - } - for i := 0; i < len(list1); i++ { - if list1[i].Hex() != list2[i].Hex() { - return false - } - } - return true -} - // snapshot retrieves the authorization snapshot at a given point in time. func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64, hash common.Hash, parents []*types.Header) (*Snapshot, error) { // Search for a snapshot in memory or on disk for checkpoints @@ -426,7 +379,7 @@ func (c *Consortium) verifySeal(chain consensus.ChainHeaderReader, header *types // Verifying the genesis block is not supported number := header.Number.Uint64() if number == 0 { - return errUnknownBlock + return consortiumCommon.ErrUnknownBlock } // Verifying the genesis block is not supported @@ -437,7 +390,7 @@ func (c *Consortium) verifySeal(chain consensus.ChainHeaderReader, header *types } // Resolve the authorization key and check against signers - signer, err := consortiumCommon.Ecrecover(header, c.signatures) + signer, err := ecrecover(header, c.signatures) if err != nil { return err } @@ -454,10 +407,10 @@ func (c *Consortium) verifySeal(chain consensus.ChainHeaderReader, header *types validators := snap.SignerList inturn := c.signerInTurn(signer, header.Number.Uint64(), validators) if inturn && header.Difficulty.Cmp(diffInTurn) != 0 { - return errWrongDifficulty + return consortiumCommon.ErrWrongDifficulty } if !inturn && header.Difficulty.Cmp(diffNoTurn) != 0 { - return errWrongDifficulty + return consortiumCommon.ErrWrongDifficulty } return nil } @@ -555,7 +508,7 @@ func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, // Sealing the genesis block is not supported number := header.Number.Uint64() if number == 0 { - return errUnknownBlock + return consortiumCommon.ErrUnknownBlock } // For 0-period chains, refuse to seal empty blocks (no reward but would spin sealing) if c.config.Period == 0 && len(block.Transactions()) == 0 { @@ -597,7 +550,7 @@ func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, log.Trace("Out-of-turn signing requested", "wiggle", common.PrettyDuration(wiggle)) } // Sign all the things! - sighash, err := signFn(accounts.Account{Address: signer}, accounts.MimetypeTextPlain, consortiumCommon.ConsortiumRLP(header)) + sighash, err := signFn(accounts.Account{Address: signer}, accounts.MimetypeTextPlain, consortiumRLP(header)) if err != nil { return err } @@ -614,7 +567,7 @@ func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, select { case results <- block.WithSeal(header): default: - log.Warn("Sealing result is not read by miner", "sealhash", consortiumCommon.SealHash(header)) + log.Warn("Sealing result is not read by miner", "sealhash", SealHash(header)) } }() @@ -623,7 +576,7 @@ func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, // SealHash returns the hash of a block prior to it being sealed. func (c *Consortium) SealHash(header *types.Header) common.Hash { - return consortiumCommon.SealHash(header) + return SealHash(header) } // Close implements consensus.Engine. It's a noop for consortium as there are no background threads. @@ -661,17 +614,6 @@ func signerInList(signer common.Address, validators []common.Address) bool { return false } -func extractAddressFromBytes(bytes []byte) []common.Address { - if bytes != nil && len(bytes) < common.AddressLength { - return []common.Address{} - } - results := make([]common.Address, len(bytes)/common.AddressLength) - for i := 0; i < len(results); i++ { - copy(results[i][:], bytes[i*common.AddressLength:]) - } - return results -} - func (c *Consortium) doCalcDifficulty(signer common.Address, number uint64, validators []common.Address) *big.Int { if c.signerInTurn(signer, number, validators) { return new(big.Int).Set(diffInTurn) @@ -717,7 +659,7 @@ func (c *Consortium) getValidatorsFromLastCheckpoint(chain consensus.ChainHeader header = chain.GetHeaderByNumber(lastCheckpoint) } extraSuffix := len(header.Extra) - consortiumCommon.ExtraSeal - return extractAddressFromBytes(header.Extra[extraVanity:extraSuffix]), nil + return consortiumCommon.ExtractAddressFromBytes(header.Extra[extraVanity:extraSuffix]), nil } // Check if it is the turn of the signer from the last checkpoint @@ -726,3 +668,72 @@ func (c *Consortium) signerInTurn(signer common.Address, number uint64, validato index := (number - lastCheckpoint) % uint64(len(validators)) return validators[index] == signer } + +// ecrecover extracts the Ethereum account address from a signed header. +func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) { + // If the signature's already cached, return that + hash := header.Hash() + if address, known := sigcache.Get(hash); known { + return address.(common.Address), nil + } + // Retrieve the signature from the header extra-data + if len(header.Extra) < consortiumCommon.ExtraSeal { + return common.Address{}, consortiumCommon.ErrMissingSignature + } + signature := header.Extra[len(header.Extra)-consortiumCommon.ExtraSeal:] + + // Recover the public key and the Ethereum address + pubkey, err := crypto.Ecrecover(SealHash(header).Bytes(), signature) + if err != nil { + return common.Address{}, err + } + var signer common.Address + copy(signer[:], crypto.Keccak256(pubkey[1:])[12:]) + + sigcache.Add(hash, signer) + return signer, nil +} + +// SealHash returns the hash of a block prior to it being sealed. +func SealHash(header *types.Header) (hash common.Hash) { + hasher := sha3.NewLegacyKeccak256() + encodeSigHeader(hasher, header) + hasher.Sum(hash[:0]) + return hash +} + +// consortiumRLP returns the rlp bytes which needs to be signed for the proof-of-authority +// sealing. The RLP to sign consists of the entire header apart from the 65 byte signature +// contained at the end of the extra data. +// +// Note, the method requires the extra data to be at least 65 bytes, otherwise it +// panics. This is done to avoid accidentally using both forms (signature present +// or not), which could be abused to produce different hashes for the same header. +func consortiumRLP(header *types.Header) []byte { + b := new(bytes.Buffer) + encodeSigHeader(b, header) + return b.Bytes() +} + +func encodeSigHeader(w io.Writer, header *types.Header) { + err := rlp.Encode(w, []interface{}{ + header.ParentHash, + header.UncleHash, + header.Coinbase, + header.Root, + header.TxHash, + header.ReceiptHash, + header.Bloom, + header.Difficulty, + header.Number, + header.GasLimit, + header.GasUsed, + header.Time, + header.Extra[:len(header.Extra)-crypto.SignatureLength], // Yes, this will panic if extra is too short + header.MixDigest, + header.Nonce, + }) + if err != nil { + panic("can't encode: " + err.Error()) + } +} diff --git a/consensus/consortium/v1/snapshot.go b/consensus/consortium/v1/snapshot.go index 9d6b8f8251..a648285534 100644 --- a/consensus/consortium/v1/snapshot.go +++ b/consensus/consortium/v1/snapshot.go @@ -18,7 +18,6 @@ package v1 import ( "encoding/json" - consortiumCommon "github.com/ethereum/go-ethereum/consensus/consortium/common" "time" "github.com/ethereum/go-ethereum/common" @@ -136,7 +135,7 @@ func (s *Snapshot) apply(chain consensus.ChainHeaderReader, c *Consortium, heade } // Resolve the authorization key and check against signers - signer, err := consortiumCommon.Ecrecover(header, s.sigcache) + signer, err := ecrecover(header, s.sigcache) if err != nil { return nil, err } diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index b5839f064f..8ddf1f8a14 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -3,18 +3,20 @@ package v2 import ( "bytes" "errors" + "fmt" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/consensus" consortiumCommon "github.com/ethereum/go-ethereum/consensus/consortium/common" + "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/systemcontracts" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" @@ -31,9 +33,11 @@ const ( inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory inmemorySignatures = 4096 // Number of recent block signatures to keep in memory - wiggleTime = 1000 * time.Millisecond // Random delay (per signer) to allow concurrent signers + checkpointInterval = 1024 // Number of blocks after which to save the snapshot to the database + + extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity + extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal - nextForkHashSize = 4 // Fixed number of extra-data suffix bytes reserved for nextForkHash. validatorBytesLength = common.AddressLength ) @@ -41,27 +45,12 @@ const ( var ( epochLength = uint64(30000) // Default number of blocks after which to checkpoint - extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity - extraSeal = crypto.SignatureLength // Fixed number of extra-data suffix bytes reserved for signer seal - - emptyNonce = hexutil.MustDecode("0x0000000000000000") // Nonce number should be empty - uncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW diffInTurn = big.NewInt(7) // Block difficulty for in-turn signatures diffNoTurn = big.NewInt(3) // Block difficulty for out-of-turn signatures ) -var ( - // 100 native token - maxSystemBalance = new(big.Int).Mul(big.NewInt(100), big.NewInt(params.Ether)) - - systemContracts = map[common.Address]bool{ - common.HexToAddress(systemcontracts.ValidatorContract): true, - common.HexToAddress(systemcontracts.SlashContract): true, - } -) - var ( // errUnauthorizedValidator is returned if a header is signed by a non-authorized entity. errUnauthorizedValidator = errors.New("unauthorized validator") @@ -77,6 +66,23 @@ var ( // errRecentlySigned is returned if a header is signed by an authorized entity // that already signed a header recently, thus is temporarily not allowed to. errRecentlySigned = errors.New("recently signed") + + // errMissingValidators is returned if you can not get list of validators. + errMissingValidators = errors.New("missing validators") + + // errCoinBaseMisMatch is returned if a header's coinbase do not match with signature + errCoinBaseMisMatch = errors.New("coinbase do not match with signature") + + // errMismatchingEpochValidators is returned if a sprint block contains a + // list of validators different from the one the local node calculated. + errMismatchingEpochValidators = errors.New("mismatching validator list on epoch block") +) + +var ( + systemContracts = map[common.Address]bool{ + common.HexToAddress(systemcontracts.ValidatorContract): true, + common.HexToAddress(systemcontracts.SlashContract): true, + } ) type SignerTxFn func(accounts.Account, *types.Transaction, *big.Int) (*types.Transaction, error) @@ -104,6 +110,8 @@ type Consortium struct { ethAPI *ethapi.PublicBlockChainAPI validatorSetABI abi.ABI slashABI abi.ABI + + fakeDiff bool } func New( @@ -184,11 +192,11 @@ func (c *Consortium) AllowLightProcess(chain consensus.ChainReader, currentHeade } func (c *Consortium) Author(header *types.Header) (common.Address, error) { - return common.Address{}, nil + return header.Coinbase, nil } func (c *Consortium) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { - return nil + return c.VerifyHeaderAndParents(chain, header, nil) } func (c *Consortium) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { @@ -199,14 +207,266 @@ func (c *Consortium) VerifyHeaders(chain consensus.ChainHeaderReader, headers [] } func (c *Consortium) VerifyHeaderAndParents(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error { - return nil + if header.Number == nil { + return consortiumCommon.ErrUnknownBlock + } + number := header.Number.Uint64() + + // Don't waste time checking blocks from the future + if header.Time > uint64(time.Now().Unix()) { + return consensus.ErrFutureBlock + } + // Check that the extra-data contains the vanity, validators and signature. + if len(header.Extra) < extraVanity { + return consortiumCommon.ErrMissingVanity + } + if len(header.Extra) < extraVanity+extraSeal { + return consortiumCommon.ErrMissingSignature + } + // check extra data + isEpoch := number%c.config.Epoch == 0 + + // Ensure that the extra-data contains a signer list on checkpoint, but none otherwise + signersBytes := len(header.Extra) - extraVanity - extraSeal + if !isEpoch && signersBytes != 0 { + return consortiumCommon.ErrExtraValidators + } + + if isEpoch && signersBytes%consortiumCommon.ValidatorBytesLength != 0 { + return consortiumCommon.ErrInvalidSpanValidators + } + + // Ensure that the mix digest is zero as we don't have fork protection currently + if header.MixDigest != (common.Hash{}) { + return consortiumCommon.ErrInvalidMixDigest + } + // Ensure that the block doesn't contain any uncles which are meaningless in PoA + if header.UncleHash != uncleHash { + return consortiumCommon.ErrInvalidUncleHash + } + // Ensure that the block's difficulty is meaningful (may not be correct at this point) + if number > 0 { + if header.Difficulty == nil { + return consortiumCommon.ErrInvalidDifficulty + } + } + // If all checks passed, validate any special fields for hard forks + if err := misc.VerifyForkHashes(chain.Config(), header, false); err != nil { + return err + } + // All basic checks passed, verify cascading fields + return c.verifyCascadingFields(chain, header, parents) +} + +func (c *Consortium) verifyCascadingFields(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error { + // The genesis block is the always valid dead-end + number := header.Number.Uint64() + if number == 0 { + return nil + } + + var parent *types.Header + if len(parents) > 0 { + parent = parents[len(parents)-1] + } else { + parent = chain.GetHeader(header.ParentHash, number-1) + } + + if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash { + return consensus.ErrUnknownAncestor + } + + // Verify list validators + // Note: Verify it in Finalize + //validators, err := c.getCurrentValidators(header.Hash(), header.Number) + //if err != nil { + // return errMissingValidators + //} + //checkpointValidators := c.getValidatorsFromHeader(header) + //validValidators := consortiumCommon.CompareSignersLists(validators, checkpointValidators) + //if !validValidators { + // log.Error("signers lists are different in checkpoint header and snapshot", "number", number, "validatorsHeader", checkpointValidators, "signers", validators) + // return consortiumCommon.ErrInvalidCheckpointSigners + //} + + // Verify that the gas limit is <= 2^63-1 + capacity := uint64(0x7fffffffffffffff) + if header.GasLimit > capacity { + return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, capacity) + } + // Verify that the gasUsed is <= gasLimit + if header.GasUsed > header.GasLimit { + return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) + } + + // Verify that the gas limit remains within allowed bounds + //diff := int64(parent.GasLimit) - int64(header.GasLimit) + //if diff < 0 { + // diff *= -1 + //} + //limit := parent.GasLimit / params.ConsortiumGasLimitBoundDivisor + // + //if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit { + // return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit) + //} + if err := misc.VerifyGaslimit(parent.GasLimit, header.GasLimit); err != nil { + return err + } + + // All basic checks passed, verify the seal and return + return c.verifySeal(chain, header, parents) } func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64, hash common.Hash, parents []*types.Header) (*Snapshot, error) { - return nil, nil + // Search for a snapshot in memory or on disk for checkpoints + var ( + headers []*types.Header + snap *Snapshot + ) + + for snap == nil { + // If an in-memory snapshot was found, use that + if s, ok := c.recents.Get(hash); ok { + snap = s.(*Snapshot) + break + } + + // If an on-disk checkpoint snapshot can be found, use that + if number%checkpointInterval == 0 { + if s, err := loadSnapshot(c.config, c.signatures, c.db, hash, c.ethAPI); err == nil { + log.Trace("Loaded snapshot from disk", "number", number, "hash", hash) + snap = s + break + } + } + + // If we're at the genesis, snapshot the initial state. + if number == 0 { + checkpoint := chain.GetHeaderByNumber(number) + if checkpoint != nil { + // get checkpoint data + hash := checkpoint.Hash() + + validatorBytes := checkpoint.Extra[extraVanity : len(checkpoint.Extra)-extraSeal] + // get validators from headers + validators, err := ParseValidators(validatorBytes) + if err != nil { + return nil, err + } + + // new snap shot + snap = newSnapshot(c.config, c.signatures, number, hash, validators, c.ethAPI) + if err := snap.store(c.db); err != nil { + return nil, err + } + log.Info("Stored checkpoint snapshot to disk", "number", number, "hash", hash) + break + } + } + + // No snapshot for this header, gather the header and move backward + var header *types.Header + if len(parents) > 0 { + // If we have explicit parents, pick from there (enforced) + header = parents[len(parents)-1] + if header.Hash() != hash || header.Number.Uint64() != number { + return nil, consensus.ErrUnknownAncestor + } + parents = parents[:len(parents)-1] + } else { + // No explicit parents (or no more left), reach out to the database + header = chain.GetHeader(hash, number) + if header == nil { + return nil, consensus.ErrUnknownAncestor + } + } + headers = append(headers, header) + number, hash = number-1, header.ParentHash + } + + // check if snapshot is nil + if snap == nil { + return nil, fmt.Errorf("unknown error while retrieving snapshot at block number %v", number) + } + + // Previous snapshot found, apply any pending headers on top of it + for i := 0; i < len(headers)/2; i++ { + headers[i], headers[len(headers)-1-i] = headers[len(headers)-1-i], headers[i] + } + + snap, err := snap.apply(headers, chain, parents, c.chainConfig.ChainID) + if err != nil { + return nil, err + } + c.recents.Add(snap.Hash, snap) + + // If we've generated a new checkpoint snapshot, save to disk + if snap.Number%checkpointInterval == 0 && len(headers) > 0 { + if err = snap.store(c.db); err != nil { + return nil, err + } + log.Trace("Stored snapshot to disk", "number", snap.Number, "hash", snap.Hash) + } + return snap, err } func (c *Consortium) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { + if len(block.Uncles()) > 0 { + return errors.New("uncles not allowed") + } + return nil +} + +// verifySeal checks whether the signature contained in the header satisfies the +// consensus protocol requirements. The method accepts an optional list of parent +// headers that aren't yet part of the local blockchain to generate the snapshots +// from. +func (c *Consortium) verifySeal(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error { + // Verifying the genesis block is not supported + number := header.Number.Uint64() + if number == 0 { + return consortiumCommon.ErrUnknownBlock + } + // Retrieve the snapshot needed to verify this header and cache it + snap, err := c.snapshot(chain, number-1, header.ParentHash, parents) + if err != nil { + return err + } + + // Resolve the authorization key and check against validators + signer, err := ecrecover(header, c.signatures, c.chainConfig.ChainID) + if err != nil { + return err + } + + if signer != header.Coinbase { + return errCoinBaseMisMatch + } + + if _, ok := snap.Validators[signer]; !ok { + return errUnauthorizedValidator + } + + for seen, recent := range snap.Recents { + if recent == signer { + // Signer is among recents, only fail if the current block doesn't shift it out + if limit := uint64(len(snap.Validators)/2 + 1); seen > number-limit { + return consortiumCommon.ErrRecentlySigned + } + } + } + + // Ensure that the difficulty corresponds to the turn-ness of the signer + if !c.fakeDiff { + inturn := snap.inturn(signer) + if inturn && header.Difficulty.Cmp(diffInTurn) != 0 { + return consortiumCommon.ErrWrongDifficulty + } + if !inturn && header.Difficulty.Cmp(diffNoTurn) != 0 { + return consortiumCommon.ErrWrongDifficulty + } + } + return nil } @@ -233,7 +493,7 @@ func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, } func (c *Consortium) SealHash(header *types.Header) common.Hash { - return common.Hash{} + return SealHash(header, c.chainConfig.ChainID) } func (c *Consortium) Close() error { @@ -248,6 +508,11 @@ func (c *Consortium) CalcDifficulty(chain consensus.ChainHeaderReader, time uint return nil } +func (c *Consortium) getValidatorsFromHeader(header *types.Header) []common.Address { + extraSuffix := len(header.Extra) - consortiumCommon.ExtraSeal + return consortiumCommon.ExtractAddressFromBytes(header.Extra[extraVanity:extraSuffix]) +} + // ecrecover extracts the Ethereum account address from a signed header. func ecrecover(header *types.Header, sigcache *lru.ARCCache, chainId *big.Int) (common.Address, error) { // If the signature's already cached, return that diff --git a/consensus/consortium/v2/consortiumv2fork.go b/consensus/consortium/v2/consortiumv2fork.go new file mode 100644 index 0000000000..4986eda3d2 --- /dev/null +++ b/consensus/consortium/v2/consortiumv2fork.go @@ -0,0 +1,13 @@ +package v2 + +import ( + "github.com/ethereum/go-ethereum/core/types" +) + +func (c *Consortium) blockTimeForConsortiumV2Fork(snap *Snapshot, header, parent *types.Header) uint64 { + blockTime := parent.Time + c.config.Period + //if c.chainConfig.IsConsortiumV2(header.Number) { + // blockTime = blockTime + backOffTime(snap, c.val) + //} + return blockTime +} diff --git a/consensus/consortium/v2/context.go b/consensus/consortium/v2/context.go new file mode 100644 index 0000000000..305e4a45b9 --- /dev/null +++ b/consensus/consortium/v2/context.go @@ -0,0 +1,21 @@ +package v2 + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/core/types" +) + +// chain context +type chainContext struct { + Chain consensus.ChainHeaderReader + consortium consensus.Engine +} + +func (c chainContext) Engine() consensus.Engine { + return c.consortium +} + +func (c chainContext) GetHeader(hash common.Hash, number uint64) *types.Header { + return c.Chain.GetHeader(hash, number) +} diff --git a/consensus/consortium/v2/contract.go b/consensus/consortium/v2/contract.go index 1b85c5fb8f..aac01acc61 100644 --- a/consensus/consortium/v2/contract.go +++ b/consensus/consortium/v2/contract.go @@ -91,6 +91,26 @@ func (c *Consortium) distributeIncoming( return c.distributeToValidator(balance, val, state, header, chain, txs, receipts, receivedTxs, usedGas, mining) } +// slash spoiled validators +func (c *Consortium) slash(spoiledVal common.Address, state *state.StateDB, header *types.Header, chain core.ChainContext, + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error { + // method + method := "slash" + + // get packed data + data, err := c.slashABI.Pack(method, + spoiledVal, + ) + if err != nil { + log.Error("Unable to pack tx for slash", "error", err) + return err + } + // get system message + msg := c.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.SlashContract), data, common.Big0) + // apply message + return c.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining) +} + func (c *Consortium) initContract( state *state.StateDB, header *types.Header, diff --git a/consensus/consortium/v2/snapshot.go b/consensus/consortium/v2/snapshot.go index 41815369d3..9c73fe1830 100644 --- a/consensus/consortium/v2/snapshot.go +++ b/consensus/consortium/v2/snapshot.go @@ -217,6 +217,12 @@ func (s *Snapshot) inturn(validator common.Address) bool { return validators[offset] == validator } +func (s *Snapshot) supposeValidator() common.Address { + validators := s.validators() + index := (s.Number + 1) % uint64(len(validators)) + return validators[index] +} + func ParseValidators(validatorsBytes []byte) ([]common.Address, error) { if len(validatorsBytes)%validatorBytesLength != 0 { return nil, errors.New("invalid validators bytes") diff --git a/params/protocol_params.go b/params/protocol_params.go index 7abb2441bf..651f4bb956 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -19,9 +19,10 @@ package params import "math/big" const ( - GasLimitBoundDivisor uint64 = 1024 // The bound divisor of the gas limit, used in update calculations. - MinGasLimit uint64 = 5000 // Minimum the gas limit may ever be. - GenesisGasLimit uint64 = 4712388 // Gas limit of the Genesis block. + GasLimitBoundDivisor uint64 = 1024 // The bound divisor of the gas limit, used in update calculations. + ConsortiumGasLimitBoundDivisor uint64 = 256 + MinGasLimit uint64 = 5000 // Minimum the gas limit may ever be. + GenesisGasLimit uint64 = 4712388 // Gas limit of the Genesis block. MaximumExtraDataSize uint64 = 32 // Maximum size extra data may be after Genesis. ExpByteGas uint64 = 10 // Times ceil(log256(exponent)) for the EXP instruction. From 1c01b4f9ce1ee36a552ed5a2fe5a59a6869c0db4 Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Wed, 17 Aug 2022 11:07:58 +0700 Subject: [PATCH 09/52] feat: implement Prepare method (#100) --- consensus/consortium/v2/consortium.go | 56 +++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index 8ddf1f8a14..00fd464168 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -24,6 +24,7 @@ import ( "golang.org/x/crypto/sha3" "io" "math/big" + "sort" "strings" "sync" "time" @@ -471,6 +472,51 @@ func (c *Consortium) verifySeal(chain consensus.ChainHeaderReader, header *types } func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { + header.Coinbase = c.val + header.Nonce = types.BlockNonce{} + + number := header.Number.Uint64() + snap, err := c.snapshot(chain, number-1, header.ParentHash, nil) + if err != nil { + return err + } + + // Set the correct difficulty + header.Difficulty = CalcDifficulty(snap, c.val) + + // Ensure the extra data has all it's components + if len(header.Extra) < extraVanity { + header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, extraVanity-len(header.Extra))...) + } + header.Extra = header.Extra[:extraVanity] + + if number%c.config.Epoch == 0 { + newValidators, err := c.getCurrentValidators(header.ParentHash, new(big.Int).Sub(header.Number, common.Big1)) + if err != nil { + return err + } + // sort validator by address + sort.Sort(validatorsAscending(newValidators)) + for _, validator := range newValidators { + header.Extra = append(header.Extra, validator.Bytes()...) + } + } + + // add extra seal space + header.Extra = append(header.Extra, make([]byte, extraSeal)...) + + // Mix digest is reserved for now, set to empty + header.MixDigest = common.Hash{} + + // Ensure the timestamp has the correct delay + parent := chain.GetHeader(header.ParentHash, number-1) + if parent == nil { + return consensus.ErrUnknownAncestor + } + header.Time = c.blockTimeForConsortiumV2Fork(snap, header, parent) + if header.Time < uint64(time.Now().Unix()) { + header.Time = uint64(time.Now().Unix()) + } return nil } @@ -508,6 +554,16 @@ func (c *Consortium) CalcDifficulty(chain consensus.ChainHeaderReader, time uint return nil } +// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty +// that a new block should have based on the previous blocks in the chain and the +// current signer. +func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int { + if snap.inturn(signer) { + return new(big.Int).Set(diffInTurn) + } + return new(big.Int).Set(diffNoTurn) +} + func (c *Consortium) getValidatorsFromHeader(header *types.Header) []common.Address { extraSuffix := len(header.Extra) - consortiumCommon.ExtraSeal return consortiumCommon.ExtractAddressFromBytes(header.Extra[extraVanity:extraSuffix]) From 8b79c7709233360c2204a6b4da989eb890fbc93e Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Wed, 17 Aug 2022 15:35:10 +0700 Subject: [PATCH 10/52] [RON-169] feat: implement Finalize and FinalizeAndAssemble methods (#101) * feat: implement Finalize and FinalizeAndAssemble methods * fix: remove init contract * fix: remove unused import * fix: missing import --- consensus/consortium/v1/api.go | 3 +- consensus/consortium/v2/consortium.go | 112 +++++++++++++++++++++++++- core/receipt_processor.go | 66 +++++++++++++++ core/state_processor.go | 33 +++++++- core/types/block.go | 2 + core/types/bloom9.go | 2 + 6 files changed, 214 insertions(+), 4 deletions(-) create mode 100644 core/receipt_processor.go diff --git a/consensus/consortium/v1/api.go b/consensus/consortium/v1/api.go index a62b61f70d..3f590da14f 100644 --- a/consensus/consortium/v1/api.go +++ b/consensus/consortium/v1/api.go @@ -19,6 +19,7 @@ package v1 import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" + consortiumCommon "github.com/ethereum/go-ethereum/consensus/consortium/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" @@ -42,7 +43,7 @@ func (api *API) GetSigners(number *rpc.BlockNumber) ([]common.Address, error) { } // Ensure we have an actually valid block and return the signers from its snapshot if header == nil { - return nil, errUnknownBlock + return nil, consortiumCommon.ErrUnknownBlock } validators, err := api.consortium.getValidatorsFromLastCheckpoint(api.chain, header.Number.Uint64(), nil) diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index 00fd464168..7161162050 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -20,6 +20,7 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/trie" lru "github.com/hashicorp/golang-lru" "golang.org/x/crypto/sha3" "io" @@ -522,12 +523,121 @@ func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.He func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs *[]*types.Transaction, uncles []*types.Header, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction, usedGas *uint64) error { + // warn if not in majority fork + number := header.Number.Uint64() + snap, err := c.snapshot(chain, number-1, header.ParentHash, nil) + if err != nil { + return err + } + + // If the block is a epoch end block, verify the validator list + // The verification can only be done when the state is ready, it can't be done in VerifyHeader. + if header.Number.Uint64()%c.config.Epoch == 0 { + newValidators, err := c.getCurrentValidators(header.ParentHash, new(big.Int).Sub(header.Number, common.Big1)) + if err != nil { + return err + } + // sort validator by address + sort.Sort(validatorsAscending(newValidators)) + validatorsBytes := make([]byte, len(newValidators)*validatorBytesLength) + for i, validator := range newValidators { + copy(validatorsBytes[i*validatorBytesLength:], validator.Bytes()) + } + + extraSuffix := len(header.Extra) - extraSeal + if !bytes.Equal(header.Extra[extraVanity:extraSuffix], validatorsBytes) { + return errMismatchingEpochValidators + } + } + // No block rewards in PoA, so the state remains as is and uncles are dropped + cx := chainContext{Chain: chain, consortium: c} + if header.Difficulty.Cmp(diffInTurn) != 0 { + spoiledVal := snap.supposeValidator() + signedRecently := false + for _, recent := range snap.Recents { + if recent == spoiledVal { + signedRecently = true + break + } + } + if !signedRecently { + log.Trace("slash validator", "block hash", header.Hash(), "address", spoiledVal) + err = c.slash(spoiledVal, state, header, cx, txs, receipts, systemTxs, usedGas, false) + if err != nil { + // it is possible that slash validator failed because of the slash channel is disabled. + log.Error("slash validator failed", "block hash", header.Hash(), "address", spoiledVal) + } + } + } + val := header.Coinbase + err = c.distributeIncoming(val, state, header, cx, txs, receipts, systemTxs, usedGas, false) + if err != nil { + return err + } + if len(*systemTxs) > 0 { + return errors.New("the length of systemTxs do not match") + } return nil } func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { - return nil, nil + // No block rewards in PoA, so the state remains as is and uncles are dropped + cx := chainContext{Chain: chain, consortium: c} + if txs == nil { + txs = make([]*types.Transaction, 0) + } + if receipts == nil { + receipts = make([]*types.Receipt, 0) + } + + if header.Difficulty.Cmp(diffInTurn) != 0 { + number := header.Number.Uint64() + snap, err := c.snapshot(chain, number-1, header.ParentHash, nil) + if err != nil { + return nil, err + } + spoiledVal := snap.supposeValidator() + signedRecently := false + for _, recent := range snap.Recents { + if recent == spoiledVal { + signedRecently = true + break + } + } + if !signedRecently { + err = c.slash(spoiledVal, state, header, cx, &txs, &receipts, nil, &header.GasUsed, true) + if err != nil { + // it is possible that slash validator failed because of the slash channel is disabled. + log.Error("slash validator failed", "block hash", header.Hash(), "address", spoiledVal) + } + } + } + err := c.distributeIncoming(c.val, state, header, cx, &txs, &receipts, nil, &header.GasUsed, true) + if err != nil { + return nil, err + } + // should not happen. Once happen, stop the node is better than broadcast the block + if header.GasLimit < header.GasUsed { + return nil, errors.New("gas consumption of system txs exceed the gas limit") + } + header.UncleHash = types.CalcUncleHash(nil) + var blk *types.Block + var rootHash common.Hash + wg := sync.WaitGroup{} + wg.Add(2) + go func() { + rootHash = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) + wg.Done() + }() + go func() { + blk = types.NewBlock(header, txs, nil, receipts, trie.NewStackTrie(nil)) + wg.Done() + }() + wg.Wait() + blk.SetRoot(rootHash) + // Assemble and return the final block for sealing + return blk, nil } func (c *Consortium) Delay(chain consensus.ChainReader, header *types.Header) *time.Duration { diff --git a/core/receipt_processor.go b/core/receipt_processor.go new file mode 100644 index 0000000000..3b4c2579cc --- /dev/null +++ b/core/receipt_processor.go @@ -0,0 +1,66 @@ +package core + +import ( + "bytes" + "sync" + + "github.com/ethereum/go-ethereum/core/types" +) + +type ReceiptProcessor interface { + Apply(receipt *types.Receipt) +} + +var ( + _ ReceiptProcessor = (*ReceiptBloomGenerator)(nil) + _ ReceiptProcessor = (*AsyncReceiptBloomGenerator)(nil) +) + +func NewReceiptBloomGenerator() *ReceiptBloomGenerator { + return &ReceiptBloomGenerator{} +} + +type ReceiptBloomGenerator struct { +} + +func (p *ReceiptBloomGenerator) Apply(receipt *types.Receipt) { + receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) +} + +func NewAsyncReceiptBloomGenerator(txNums int) *AsyncReceiptBloomGenerator { + generator := &AsyncReceiptBloomGenerator{ + receipts: make(chan *types.Receipt, txNums), + } + generator.startWorker() + return generator +} + +type AsyncReceiptBloomGenerator struct { + receipts chan *types.Receipt + wg sync.WaitGroup + isClosed bool +} + +func (p *AsyncReceiptBloomGenerator) startWorker() { + p.wg.Add(1) + go func() { + defer p.wg.Done() + for receipt := range p.receipts { + if receipt != nil && bytes.Equal(receipt.Bloom[:], types.EmptyBloom[:]) { + receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) + } + } + }() +} + +func (p *AsyncReceiptBloomGenerator) Apply(receipt *types.Receipt) { + if !p.isClosed { + p.receipts <- receipt + } +} + +func (p *AsyncReceiptBloomGenerator) Close() { + close(p.receipts) + p.isClosed = true + p.wg.Wait() +} diff --git a/core/state_processor.go b/core/state_processor.go index b3dbbe2705..e182f858ed 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -83,8 +83,22 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg systemTxs := make([]*types.Transaction, 0, 2) + posa, isPoSA := p.engine.(consensus.PoSA) + + bloomProcessors := NewAsyncReceiptBloomGenerator(txNum) + defer bloomProcessors.Close() + // Iterate over and process the individual transactions for i, tx := range block.Transactions() { + if isPoSA { + if isSystemTx, err := posa.IsSystemTransaction(tx, block.Header()); err != nil { + return nil, nil, 0, err + } else if isSystemTx { + systemTxs = append(systemTxs, tx) + continue + } + } + // set current transaction in block context to each transaction vmenv.Context.CurrentTransaction = tx // reset counter to start counting opcodes in new transaction @@ -94,7 +108,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) } statedb.Prepare(tx.Hash(), i) - receipt, _, err := applyTransaction(msg, p.config, p.bc, nil, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv) + receipt, _, err := applyTransaction(msg, p.config, p.bc, nil, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv, bloomProcessors) if err != nil { return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) } @@ -115,7 +129,19 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg return receipts, allLogs, *usedGas, nil } -func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, *ExecutionResult, error) { +func applyTransaction( + msg types.Message, + config *params.ChainConfig, + bc ChainContext, + author *common.Address, + gp *GasPool, + statedb *state.StateDB, + blockNumber *big.Int, + blockHash common.Hash, + tx *types.Transaction, + usedGas *uint64, evm *vm.EVM, + receiptProcessors ...ReceiptProcessor, +) (*types.Receipt, *ExecutionResult, error) { // Create a new context to be used in the EVM environment. txContext := NewEVMTxContext(msg) evm.Reset(txContext, statedb) @@ -174,6 +200,9 @@ func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainCon receipt.BlockHash = blockHash receipt.BlockNumber = blockNumber receipt.TransactionIndex = uint(statedb.TxIndex()) + for _, receiptProcessor := range receiptProcessors { + receiptProcessor.Apply(receipt) + } return receipt, result, err } diff --git a/core/types/block.go b/core/types/block.go index 7459dbb2e0..aa6ad67358 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -325,6 +325,8 @@ func (b *Block) Size() common.StorageSize { return common.StorageSize(c) } +func (b *Block) SetRoot(root common.Hash) { b.header.Root = root } + // SanityCheck can be used to prevent that unbounded fields are // stuffed with junk data to add processing overhead func (b *Block) SanityCheck() error { diff --git a/core/types/bloom9.go b/core/types/bloom9.go index 1793c2adc7..342a0b0ec3 100644 --- a/core/types/bloom9.go +++ b/core/types/bloom9.go @@ -37,6 +37,8 @@ const ( BloomBitLength = 8 * BloomByteLength ) +var EmptyBloom = Bloom{} + // Bloom represents a 2048 bit bloom filter. type Bloom [BloomByteLength]byte From 2c801712fc81ae5947548b5b279c7d4325462cb8 Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Wed, 17 Aug 2022 15:42:53 +0700 Subject: [PATCH 11/52] feat (dnk90): Add sample generated code of validators SC (#103) --- .../generated_contracts/validators/main.go | 375 ++++++++++++++++++ 1 file changed, 375 insertions(+) create mode 100644 core/systemcontracts/generated_contracts/validators/main.go diff --git a/core/systemcontracts/generated_contracts/validators/main.go b/core/systemcontracts/generated_contracts/validators/main.go new file mode 100644 index 0000000000..4b3b5e8512 --- /dev/null +++ b/core/systemcontracts/generated_contracts/validators/main.go @@ -0,0 +1,375 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package validators + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// ValidatorsMetaData contains all meta data concerning the Validators contract. +var ValidatorsMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"currentValidatorSet\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"consensusAddress\",\"type\":\"address\"},{\"internalType\":\"addresspayable\",\"name\":\"feeAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jailTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reward\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"currentValidatorSetMap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"valAddr\",\"type\":\"address\"}],\"name\":\"depositReward\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastUpdated\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getValidators\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateValidators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +} + +// ValidatorsABI is the input ABI used to generate the binding from. +// Deprecated: Use ValidatorsMetaData.ABI instead. +var ValidatorsABI = ValidatorsMetaData.ABI + +// Validators is an auto generated Go binding around an Ethereum contract. +type Validators struct { + ValidatorsCaller // Read-only binding to the contract + ValidatorsTransactor // Write-only binding to the contract + ValidatorsFilterer // Log filterer for contract events +} + +// ValidatorsCaller is an auto generated read-only Go binding around an Ethereum contract. +type ValidatorsCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ValidatorsTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ValidatorsTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ValidatorsFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ValidatorsFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ValidatorsSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ValidatorsSession struct { + Contract *Validators // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ValidatorsCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ValidatorsCallerSession struct { + Contract *ValidatorsCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ValidatorsTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ValidatorsTransactorSession struct { + Contract *ValidatorsTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ValidatorsRaw is an auto generated low-level Go binding around an Ethereum contract. +type ValidatorsRaw struct { + Contract *Validators // Generic contract binding to access the raw methods on +} + +// ValidatorsCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ValidatorsCallerRaw struct { + Contract *ValidatorsCaller // Generic read-only contract binding to access the raw methods on +} + +// ValidatorsTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ValidatorsTransactorRaw struct { + Contract *ValidatorsTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewValidators creates a new instance of Validators, bound to a specific deployed contract. +func NewValidators(address common.Address, backend bind.ContractBackend) (*Validators, error) { + contract, err := bindValidators(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Validators{ValidatorsCaller: ValidatorsCaller{contract: contract}, ValidatorsTransactor: ValidatorsTransactor{contract: contract}, ValidatorsFilterer: ValidatorsFilterer{contract: contract}}, nil +} + +// NewValidatorsCaller creates a new read-only instance of Validators, bound to a specific deployed contract. +func NewValidatorsCaller(address common.Address, caller bind.ContractCaller) (*ValidatorsCaller, error) { + contract, err := bindValidators(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ValidatorsCaller{contract: contract}, nil +} + +// NewValidatorsTransactor creates a new write-only instance of Validators, bound to a specific deployed contract. +func NewValidatorsTransactor(address common.Address, transactor bind.ContractTransactor) (*ValidatorsTransactor, error) { + contract, err := bindValidators(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ValidatorsTransactor{contract: contract}, nil +} + +// NewValidatorsFilterer creates a new log filterer instance of Validators, bound to a specific deployed contract. +func NewValidatorsFilterer(address common.Address, filterer bind.ContractFilterer) (*ValidatorsFilterer, error) { + contract, err := bindValidators(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ValidatorsFilterer{contract: contract}, nil +} + +// bindValidators binds a generic wrapper to an already deployed contract. +func bindValidators(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(ValidatorsABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Validators *ValidatorsRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Validators.Contract.ValidatorsCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Validators *ValidatorsRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Validators.Contract.ValidatorsTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Validators *ValidatorsRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Validators.Contract.ValidatorsTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Validators *ValidatorsCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Validators.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Validators *ValidatorsTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Validators.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Validators *ValidatorsTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Validators.Contract.contract.Transact(opts, method, params...) +} + +// CurrentValidatorSet is a free data retrieval call binding the contract method 0x6969a25c. +// +// Solidity: function currentValidatorSet(uint256 ) view returns(address consensusAddress, address feeAddress, uint256 totalAmount, uint256 jailTime, uint256 reward) +func (_Validators *ValidatorsCaller) CurrentValidatorSet(opts *bind.CallOpts, arg0 *big.Int) (struct { + ConsensusAddress common.Address + FeeAddress common.Address + TotalAmount *big.Int + JailTime *big.Int + Reward *big.Int +}, error) { + var out []interface{} + err := _Validators.contract.Call(opts, &out, "currentValidatorSet", arg0) + + outstruct := new(struct { + ConsensusAddress common.Address + FeeAddress common.Address + TotalAmount *big.Int + JailTime *big.Int + Reward *big.Int + }) + if err != nil { + return *outstruct, err + } + + outstruct.ConsensusAddress = *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + outstruct.FeeAddress = *abi.ConvertType(out[1], new(common.Address)).(*common.Address) + outstruct.TotalAmount = *abi.ConvertType(out[2], new(*big.Int)).(**big.Int) + outstruct.JailTime = *abi.ConvertType(out[3], new(*big.Int)).(**big.Int) + outstruct.Reward = *abi.ConvertType(out[4], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +// CurrentValidatorSet is a free data retrieval call binding the contract method 0x6969a25c. +// +// Solidity: function currentValidatorSet(uint256 ) view returns(address consensusAddress, address feeAddress, uint256 totalAmount, uint256 jailTime, uint256 reward) +func (_Validators *ValidatorsSession) CurrentValidatorSet(arg0 *big.Int) (struct { + ConsensusAddress common.Address + FeeAddress common.Address + TotalAmount *big.Int + JailTime *big.Int + Reward *big.Int +}, error) { + return _Validators.Contract.CurrentValidatorSet(&_Validators.CallOpts, arg0) +} + +// CurrentValidatorSet is a free data retrieval call binding the contract method 0x6969a25c. +// +// Solidity: function currentValidatorSet(uint256 ) view returns(address consensusAddress, address feeAddress, uint256 totalAmount, uint256 jailTime, uint256 reward) +func (_Validators *ValidatorsCallerSession) CurrentValidatorSet(arg0 *big.Int) (struct { + ConsensusAddress common.Address + FeeAddress common.Address + TotalAmount *big.Int + JailTime *big.Int + Reward *big.Int +}, error) { + return _Validators.Contract.CurrentValidatorSet(&_Validators.CallOpts, arg0) +} + +// CurrentValidatorSetMap is a free data retrieval call binding the contract method 0xad3c9da6. +// +// Solidity: function currentValidatorSetMap(address ) view returns(uint256) +func (_Validators *ValidatorsCaller) CurrentValidatorSetMap(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { + var out []interface{} + err := _Validators.contract.Call(opts, &out, "currentValidatorSetMap", arg0) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// CurrentValidatorSetMap is a free data retrieval call binding the contract method 0xad3c9da6. +// +// Solidity: function currentValidatorSetMap(address ) view returns(uint256) +func (_Validators *ValidatorsSession) CurrentValidatorSetMap(arg0 common.Address) (*big.Int, error) { + return _Validators.Contract.CurrentValidatorSetMap(&_Validators.CallOpts, arg0) +} + +// CurrentValidatorSetMap is a free data retrieval call binding the contract method 0xad3c9da6. +// +// Solidity: function currentValidatorSetMap(address ) view returns(uint256) +func (_Validators *ValidatorsCallerSession) CurrentValidatorSetMap(arg0 common.Address) (*big.Int, error) { + return _Validators.Contract.CurrentValidatorSetMap(&_Validators.CallOpts, arg0) +} + +// GetLastUpdated is a free data retrieval call binding the contract method 0x78121dd4. +// +// Solidity: function getLastUpdated() view returns(uint256) +func (_Validators *ValidatorsCaller) GetLastUpdated(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Validators.contract.Call(opts, &out, "getLastUpdated") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetLastUpdated is a free data retrieval call binding the contract method 0x78121dd4. +// +// Solidity: function getLastUpdated() view returns(uint256) +func (_Validators *ValidatorsSession) GetLastUpdated() (*big.Int, error) { + return _Validators.Contract.GetLastUpdated(&_Validators.CallOpts) +} + +// GetLastUpdated is a free data retrieval call binding the contract method 0x78121dd4. +// +// Solidity: function getLastUpdated() view returns(uint256) +func (_Validators *ValidatorsCallerSession) GetLastUpdated() (*big.Int, error) { + return _Validators.Contract.GetLastUpdated(&_Validators.CallOpts) +} + +// GetValidators is a free data retrieval call binding the contract method 0xb7ab4db5. +// +// Solidity: function getValidators() view returns(address[]) +func (_Validators *ValidatorsCaller) GetValidators(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _Validators.contract.Call(opts, &out, "getValidators") + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +// GetValidators is a free data retrieval call binding the contract method 0xb7ab4db5. +// +// Solidity: function getValidators() view returns(address[]) +func (_Validators *ValidatorsSession) GetValidators() ([]common.Address, error) { + return _Validators.Contract.GetValidators(&_Validators.CallOpts) +} + +// GetValidators is a free data retrieval call binding the contract method 0xb7ab4db5. +// +// Solidity: function getValidators() view returns(address[]) +func (_Validators *ValidatorsCallerSession) GetValidators() ([]common.Address, error) { + return _Validators.Contract.GetValidators(&_Validators.CallOpts) +} + +// DepositReward is a paid mutator transaction binding the contract method 0x6ffa4dc1. +// +// Solidity: function depositReward(address valAddr) payable returns() +func (_Validators *ValidatorsTransactor) DepositReward(opts *bind.TransactOpts, valAddr common.Address) (*types.Transaction, error) { + return _Validators.contract.Transact(opts, "depositReward", valAddr) +} + +// DepositReward is a paid mutator transaction binding the contract method 0x6ffa4dc1. +// +// Solidity: function depositReward(address valAddr) payable returns() +func (_Validators *ValidatorsSession) DepositReward(valAddr common.Address) (*types.Transaction, error) { + return _Validators.Contract.DepositReward(&_Validators.TransactOpts, valAddr) +} + +// DepositReward is a paid mutator transaction binding the contract method 0x6ffa4dc1. +// +// Solidity: function depositReward(address valAddr) payable returns() +func (_Validators *ValidatorsTransactorSession) DepositReward(valAddr common.Address) (*types.Transaction, error) { + return _Validators.Contract.DepositReward(&_Validators.TransactOpts, valAddr) +} + +// UpdateValidators is a paid mutator transaction binding the contract method 0x2d497ba2. +// +// Solidity: function updateValidators() returns() +func (_Validators *ValidatorsTransactor) UpdateValidators(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Validators.contract.Transact(opts, "updateValidators") +} + +// UpdateValidators is a paid mutator transaction binding the contract method 0x2d497ba2. +// +// Solidity: function updateValidators() returns() +func (_Validators *ValidatorsSession) UpdateValidators() (*types.Transaction, error) { + return _Validators.Contract.UpdateValidators(&_Validators.TransactOpts) +} + +// UpdateValidators is a paid mutator transaction binding the contract method 0x2d497ba2. +// +// Solidity: function updateValidators() returns() +func (_Validators *ValidatorsTransactorSession) UpdateValidators() (*types.Transaction, error) { + return _Validators.Contract.UpdateValidators(&_Validators.TransactOpts) +} From a4881192cc0cadb4872008e929537adc0b7516c9 Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Fri, 19 Aug 2022 14:09:32 +0700 Subject: [PATCH 12/52] [DPoS] fix: call smart contract through backend instead of ethapi (#104) * fix: call smart contract through backend instead of ethapi * feat: Add BlockContext to simulated backend to prevent cycle import while using it in consensus package * refactor: move contract to common * fix: case sensitive * fix: case sensitive * fix: remove NewFaker * fix: case sensitive * refactor: call opts with BlockNumber * fix: add missing header * fix: assign systemTxs to ReceivedTxs * feat (dnk90): Add balance to system address instead of coinbase, if block number is within consortiumV2 fork * update (dnk90): use IsConsortiumV2 function instead * refactor: impl Backend interface * fix: spelling mistake * refactor: eliminate magic number * refactor: call update validators * fix: checkpoint time * fix: replace manual calculation by IsOnConsortiumV2 Co-authored-by: kien Dang --- .../consortium/{v2 => common}/context.go | 13 +- consensus/consortium/common/contract.go | 310 ++++++++++++++++++ consensus/consortium/common/types.go | 8 +- consensus/consortium/main.go | 7 +- consensus/consortium/v1/consortium.go | 98 ++++-- consensus/consortium/v2/abi.go | 5 - consensus/consortium/v2/consortium.go | 133 +++++--- consensus/consortium/v2/contract.go | 304 ----------------- core/state_transition.go | 11 +- internal/ethapi/api.go | 4 + params/config.go | 29 +- 11 files changed, 530 insertions(+), 392 deletions(-) rename consensus/consortium/{v2 => common}/context.go (53%) create mode 100644 consensus/consortium/common/contract.go delete mode 100644 consensus/consortium/v2/abi.go delete mode 100644 consensus/consortium/v2/contract.go diff --git a/consensus/consortium/v2/context.go b/consensus/consortium/common/context.go similarity index 53% rename from consensus/consortium/v2/context.go rename to consensus/consortium/common/context.go index 305e4a45b9..c1b1cea284 100644 --- a/consensus/consortium/v2/context.go +++ b/consensus/consortium/common/context.go @@ -1,4 +1,4 @@ -package v2 +package common import ( "github.com/ethereum/go-ethereum/common" @@ -6,16 +6,15 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) -// chain context -type chainContext struct { +type ChainContext struct { Chain consensus.ChainHeaderReader - consortium consensus.Engine + Consortium consensus.Engine } -func (c chainContext) Engine() consensus.Engine { - return c.consortium +func (c ChainContext) Engine() consensus.Engine { + return c.Consortium } -func (c chainContext) GetHeader(hash common.Hash, number uint64) *types.Header { +func (c ChainContext) GetHeader(hash common.Hash, number uint64) *types.Header { return c.Chain.GetHeader(hash, number) } diff --git a/consensus/consortium/common/contract.go b/consensus/consortium/common/contract.go new file mode 100644 index 0000000000..d47c5aa923 --- /dev/null +++ b/consensus/consortium/common/contract.go @@ -0,0 +1,310 @@ +package common + +import ( + "bytes" + "context" + "encoding/hex" + "errors" + "fmt" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/systemcontracts/generated_contracts/validators" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/log" + chainParams "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rpc" + "math/big" +) + +var errMethodUnimplemented = errors.New("method is unimplemented") + +type ContractIntegrator struct { + signer types.Signer + validatorSC *validators.Validators +} + +func NewContractIntegrator(config *chainParams.ChainConfig, ee *ethapi.PublicBlockChainAPI) (*ContractIntegrator, error) { + backend := NewConsortiumBackend(ee) + + validatorSC, err := validators.NewValidators(config.ConsortiumV2Contracts.ValidatorSC, &backend) + if err != nil { + return nil, err + } + + return &ContractIntegrator{ + validatorSC: validatorSC, + }, nil +} + +func (c *ContractIntegrator) GetValidators(header *types.Header) ([]common.Address, error) { + addresses, err := c.validatorSC.GetValidators(&bind.CallOpts{ + BlockNumber: new(big.Int).Sub(header.Number, common.Big1), + }) + if err != nil { + return nil, err + } + + return addresses, nil +} + +func (c *ContractIntegrator) UpdateValidators(header *types.Header, opts *ApplyTransactOpts) error { + coinbase := opts.Header.Coinbase + nonce := opts.State.GetNonce(coinbase) + + tx, err := c.validatorSC.UpdateValidators(&bind.TransactOpts{ + From: coinbase, + GasLimit: math.MaxUint64 / 2, + GasPrice: big.NewInt(0), + Value: new(big.Int).SetUint64(0), + Nonce: new(big.Int).SetUint64(nonce), + NoSend: true, + }) + if err != nil { + return err + } + + msg, err := tx.AsMessage(c.signer, big.NewInt(0)) + if err != nil { + return err + } + + err = applyTransaction(msg, opts) + if err != nil { + return err + } + + return err +} + +func (c *ContractIntegrator) DistributeRewards(to common.Address, opts *ApplyTransactOpts) error { + coinbase := opts.Header.Coinbase + balance := opts.State.GetBalance(consensus.SystemAddress) + if balance.Cmp(common.Big0) <= 0 { + return nil + } + opts.State.SetBalance(consensus.SystemAddress, big.NewInt(0)) + opts.State.AddBalance(coinbase, balance) + + log.Trace("distribute to validator contract", "block hash", opts.Header.Hash(), "amount", balance) + nonce := opts.State.GetNonce(coinbase) + tx, err := c.validatorSC.DepositReward(&bind.TransactOpts{ + From: coinbase, + GasLimit: math.MaxUint64 / 2, + GasPrice: big.NewInt(0), + Value: balance, + Nonce: new(big.Int).SetUint64(nonce), + NoSend: true, + }, to) + if err != nil { + return err + } + + msg, err := tx.AsMessage(c.signer, big.NewInt(0)) + if err != nil { + return err + } + + err = applyTransaction(msg, opts) + if err != nil { + return err + } + + return nil +} + +func (c *ContractIntegrator) Slash(to common.Address, opts *ApplyTransactOpts) error { + return nil +} + +type ApplyMessageOpts struct { + State *state.StateDB + Header *types.Header + ChainConfig *chainParams.ChainConfig + ChainContext core.ChainContext +} + +type ApplyTransactOpts struct { + *ApplyMessageOpts + Txs *[]*types.Transaction + Receipts *[]*types.Receipt + ReceivedTxs *[]*types.Transaction + UsedGas *uint64 + Mining bool + Signer types.Signer + SignTxFn SignerTxFn + EthAPI *ethapi.PublicBlockChainAPI +} + +func applyTransaction(msg types.Message, opts *ApplyTransactOpts) (err error) { + signer := opts.Signer + signTxFn := opts.SignTxFn + miner := opts.Header.Coinbase + mining := opts.Mining + chainConfig := opts.ChainConfig + receivedTxs := opts.ReceivedTxs + txs := opts.Txs + header := opts.Header + receipts := opts.Receipts + usedGas := opts.UsedGas + nonce := msg.Nonce() + + expectedTx := types.NewTransaction(nonce, *msg.To(), msg.Value(), msg.Gas(), msg.GasPrice(), msg.Data()) + expectedHash := signer.Hash(expectedTx) + + if msg.From() == miner && mining { + expectedTx, err = signTxFn(accounts.Account{Address: msg.From()}, expectedTx, chainConfig.ChainID) + if err != nil { + return err + } + } else { + if receivedTxs == nil || len(*receivedTxs) == 0 || (*receivedTxs)[0] == nil { + return errors.New("supposed to get a actual transaction, but get none") + } + actualTx := (*receivedTxs)[0] + if !bytes.Equal(signer.Hash(actualTx).Bytes(), expectedHash.Bytes()) { + return fmt.Errorf("expected tx hash %v, get %v, nonce %d, to %s, value %s, gas %d, gasPrice %s, data %s", expectedHash.String(), actualTx.Hash().String(), + expectedTx.Nonce(), + expectedTx.To().String(), + expectedTx.Value().String(), + expectedTx.Gas(), + expectedTx.GasPrice().String(), + hex.EncodeToString(expectedTx.Data()), + ) + } + expectedTx = actualTx + // move to next + *receivedTxs = (*receivedTxs)[1:] + } + opts.State.Prepare(expectedTx.Hash(), len(*txs)) + gasUsed, err := applyMessage(msg, opts.ApplyMessageOpts) + if err != nil { + return err + } + *txs = append(*txs, expectedTx) + var root []byte + if chainConfig.IsByzantium(opts.Header.Number) { + opts.State.Finalise(true) + } else { + root = opts.State.IntermediateRoot(chainConfig.IsEIP158(opts.Header.Number)).Bytes() + } + *usedGas += gasUsed + receipt := types.NewReceipt(root, false, *usedGas) + receipt.TxHash = expectedTx.Hash() + receipt.GasUsed = gasUsed + + // Set the receipt logs and create a bloom for filtering + receipt.Logs = opts.State.GetLogs(expectedTx.Hash(), header.Hash()) + receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) + receipt.BlockHash = header.Hash() + receipt.BlockNumber = header.Number + receipt.TransactionIndex = uint(opts.State.TxIndex()) + *receipts = append(*receipts, receipt) + opts.State.SetNonce(msg.From(), nonce+1) + return nil +} + +func applyMessage( + msg types.Message, + opts *ApplyMessageOpts, +) (uint64, error) { + // Create a new context to be used in the EVM environment + context := core.NewEVMBlockContext(opts.Header, opts.ChainContext, nil) + // Create a new environment which holds all relevant information + // about the transaction and calling mechanisms. + vmenv := vm.NewEVM(context, vm.TxContext{Origin: msg.From(), GasPrice: big.NewInt(0)}, opts.State, opts.ChainConfig, vm.Config{}) + // Apply the transaction to the current State (included in the env) + ret, returnGas, err := vmenv.Call( + vm.AccountRef(msg.From()), + *msg.To(), + msg.Data(), + msg.Gas(), + msg.Value(), + ) + if err != nil { + log.Error("apply message failed", "msg", string(ret), "err", err) + } + return msg.Gas() - returnGas, err +} + +type ConsortiumBackend struct { + ee *ethapi.PublicBlockChainAPI +} + +func NewConsortiumBackend(ee *ethapi.PublicBlockChainAPI) ConsortiumBackend { + return ConsortiumBackend{ + ee, + } +} + +func (b *ConsortiumBackend) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) { + block := rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(blockNumber.Int64())) + result, err := b.ee.GetCode(ctx, contract, block) + if err != nil { + return nil, err + } + + return result.MarshalText() +} + +func (b *ConsortiumBackend) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { + block := rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(blockNumber.Int64())) + gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2)) + data := (hexutil.Bytes)(call.Data) + + result, err := b.ee.Call(ctx, ethapi.TransactionArgs{ + Gas: &gas, + To: call.To, + Data: &data, + }, block, nil) + if err != nil { + return nil, err + } + + return result.MarshalText() +} + +func (b *ConsortiumBackend) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { + return b.ee.GetHeader(ctx, rpc.BlockNumber(number.Int64())) +} + +func (b *ConsortiumBackend) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) { + return nil, errMethodUnimplemented +} + +func (b *ConsortiumBackend) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { + return 0, errMethodUnimplemented +} + +func (b *ConsortiumBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error) { + return big.NewInt(0), nil +} + +func (b *ConsortiumBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { + return big.NewInt(0), nil +} + +func (b *ConsortiumBackend) EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error) { + return math.MaxUint64 / 2, nil +} + +func (b *ConsortiumBackend) SendTransaction(ctx context.Context, tx *types.Transaction) error { + // No need to send transaction + return errMethodUnimplemented +} + +func (b *ConsortiumBackend) FilterLogs(ctx context.Context, query ethereum.FilterQuery) ([]types.Log, error) { + return nil, errMethodUnimplemented +} + +func (b *ConsortiumBackend) SubscribeFilterLogs(ctx context.Context, query ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) { + return nil, errMethodUnimplemented +} diff --git a/consensus/consortium/common/types.go b/consensus/consortium/common/types.go index 3972f8cfc4..c707561b73 100644 --- a/consensus/consortium/common/types.go +++ b/consensus/consortium/common/types.go @@ -1,7 +1,13 @@ package common -import "github.com/ethereum/go-ethereum/accounts" +import ( + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/core/types" + "math/big" +) // SignerFn is a signer callback function to request a header to be signed by a // backing account. type SignerFn func(accounts.Account, string, []byte) ([]byte, error) + +type SignerTxFn func(accounts.Account, *types.Transaction, *big.Int) (*types.Transaction, error) diff --git a/consensus/consortium/main.go b/consensus/consortium/main.go index 5ac0870238..ba265e4900 100644 --- a/consensus/consortium/main.go +++ b/consensus/consortium/main.go @@ -26,7 +26,7 @@ type Consortium struct { // signers set to the ones provided by the user. func New(chainConfig *params.ChainConfig, db ethdb.Database, ee *ethapi.PublicBlockChainAPI, genesisHash common.Hash) *Consortium { // Set any missing consensus parameters to their defaults - consortiumV1 := v1.New(chainConfig.Consortium, db) + consortiumV1 := v1.New(chainConfig, db, ee) consortiumV2 := v2.New(chainConfig, db, ee, genesisHash) return &Consortium{ @@ -155,8 +155,9 @@ func (c *Consortium) CalcDifficulty(chain consensus.ChainHeaderReader, time uint } // Authorize backward compatible for consortium v1 -func (c *Consortium) Authorize(signer common.Address, signFn consortiumCommon.SignerFn) { - c.v1.Authorize(signer, signFn) +func (c *Consortium) Authorize(signer common.Address, signFn consortiumCommon.SignerFn, signTxFn consortiumCommon.SignerTxFn) { + c.v1.Authorize(signer, signFn, signTxFn) + c.v2.Authorize(signer, signFn, signTxFn) } // SetGetSCValidatorsFn backward compatible for consortium v1 diff --git a/consensus/consortium/v1/consortium.go b/consensus/consortium/v1/consortium.go index ab2b4c49e1..f96516c792 100644 --- a/consensus/consortium/v1/consortium.go +++ b/consensus/consortium/v1/consortium.go @@ -21,6 +21,7 @@ import ( "bytes" "errors" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/rlp" "golang.org/x/crypto/sha3" "io" @@ -93,17 +94,24 @@ var ( // Consortium is the proof-of-authority consensus engine proposed to support the // Ethereum testnet following the Ropsten attacks. type Consortium struct { - config *params.ConsortiumConfig // Consensus engine configuration parameters - db ethdb.Database // Database to store and retrieve snapshot checkpoints + chainConfig *params.ChainConfig + config *params.ConsortiumConfig // Consensus engine configuration parameters + db ethdb.Database // Database to store and retrieve snapshot checkpoints recents *lru.ARCCache // Snapshots for recent block to speed up reorgs signatures *lru.ARCCache // Signatures of recent blocks to speed up mining proposals map[common.Address]bool // Current list of proposals we are pushing - signer common.Address // Ethereum address of the signing key - signFn consortiumCommon.SignerFn // Signer function to authorize hashes with - lock sync.RWMutex // Protects the signer fields + val common.Address // Ethereum address of the signing key + signer types.Signer + signFn consortiumCommon.SignerFn // Signer function to authorize hashes with + signTxFn consortiumCommon.SignerTxFn + + lock sync.RWMutex // Protects the signer fields + + contract *consortiumCommon.ContractIntegrator + ethAPI *ethapi.PublicBlockChainAPI getSCValidators func() ([]common.Address, error) // Get the list of validator from contract getFenixValidators func() ([]common.Address, error) // Get the validator list from Ronin Validator contract of Fenix hardfork @@ -111,22 +119,25 @@ type Consortium struct { // New creates a Consortium proof-of-authority consensus engine with the initial // signers set to the ones provided by the user. -func New(config *params.ConsortiumConfig, db ethdb.Database) *Consortium { +func New(chainConfig *params.ChainConfig, db ethdb.Database, ethAPI *ethapi.PublicBlockChainAPI) *Consortium { // Set any missing consensus parameters to their defaults - conf := *config - if conf.Epoch == 0 { - conf.Epoch = epochLength + consortiumConfig := *chainConfig.Consortium + if consortiumConfig.Epoch == 0 { + consortiumConfig.Epoch = epochLength } // Allocate the snapshot caches and create the engine recents, _ := lru.NewARC(inmemorySnapshots) signatures, _ := lru.NewARC(inmemorySignatures) return &Consortium{ - config: &conf, - db: db, - recents: recents, - signatures: signatures, - proposals: make(map[common.Address]bool), + chainConfig: chainConfig, + config: &consortiumConfig, + db: db, + recents: recents, + signatures: signatures, + ethAPI: ethAPI, + proposals: make(map[common.Address]bool), + signer: types.NewEIP155Signer(chainConfig.ChainID), } } @@ -418,8 +429,12 @@ func (c *Consortium) verifySeal(chain consensus.ChainHeaderReader, header *types // Prepare implements consensus.Engine, preparing all the consensus fields of the // header for running the transactions on top. func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { + if err := c.initContract(); err != nil { + return err + } + // Set the Coinbase address as the signer - header.Coinbase = c.signer + header.Coinbase = c.val header.Nonce = types.BlockNonce{} number := header.Number.Uint64() @@ -428,7 +443,7 @@ func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.He return err } // Set the correct difficulty - header.Difficulty = c.doCalcDifficulty(c.signer, number, validators) + header.Difficulty = c.doCalcDifficulty(c.val, number, validators) // Ensure the extra data has all its components if len(header.Extra) < extraVanity { @@ -467,6 +482,10 @@ func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.He // rewards given. func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs *[]*types.Transaction, uncles []*types.Header, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction, usedGas *uint64) error { + if err := c.initContract(); err != nil { + return err + } + // No block rewards in PoA, so the state remains as is and uncles are dropped header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) header.UncleHash = types.CalcUncleHash(nil) @@ -478,22 +497,49 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H // nor block rewards given, and returns the final block. func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { + if err := c.initContract(); err != nil { + return nil, err + } + // No block rewards in PoA, so the state remains as is and uncles are dropped header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) header.UncleHash = types.CalcUncleHash(nil) + if c.chainConfig.IsOnConsortiumV2(header.Number.Add(header.Number, common.Big1)) { + transactOpts := &consortiumCommon.ApplyTransactOpts{ + ApplyMessageOpts: &consortiumCommon.ApplyMessageOpts{ + State: state, + Header: header, + ChainConfig: c.chainConfig, + ChainContext: consortiumCommon.ChainContext{Chain: chain, Consortium: c}, + }, + Txs: &txs, + Receipts: &receipts, + ReceivedTxs: nil, + UsedGas: &header.GasUsed, + Mining: false, + Signer: c.signer, + SignTxFn: c.signTxFn, + EthAPI: c.ethAPI, + } + if err := c.contract.UpdateValidators(header, transactOpts); err != nil { + log.Error("Failed to update validators: ", err) + } + } + // Assemble and return the final block for sealing return types.NewBlock(header, txs, nil, receipts, new(trie.Trie)), nil } // Authorize injects a private key into the consensus engine to mint new blocks // with. -func (c *Consortium) Authorize(signer common.Address, signFn consortiumCommon.SignerFn) { +func (c *Consortium) Authorize(signer common.Address, signFn consortiumCommon.SignerFn, signTxFn consortiumCommon.SignerTxFn) { c.lock.Lock() defer c.lock.Unlock() - c.signer = signer + c.val = signer c.signFn = signFn + c.signTxFn = signTxFn } func (c *Consortium) Delay(chain consensus.ChainReader, header *types.Header) *time.Duration { @@ -516,14 +562,14 @@ func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, } // Don't hold the signer fields for the entire sealing procedure c.lock.RLock() - signer, signFn := c.signer, c.signFn + signer, signFn := c.val, c.signFn c.lock.RUnlock() validators, err := c.getValidatorsFromLastCheckpoint(chain, number-1, nil) if err != nil { return err } - if !signerInList(c.signer, validators) { + if !signerInList(c.val, validators) { return errUnauthorizedSigner } snap, err := c.snapshot(chain, number-1, header.ParentHash, nil) @@ -602,7 +648,7 @@ func (c *Consortium) CalcDifficulty(chain consensus.ChainHeaderReader, time uint if err != nil { return nil } - return c.doCalcDifficulty(c.signer, number, validators) + return c.doCalcDifficulty(c.val, number, validators) } func signerInList(signer common.Address, validators []common.Address) bool { @@ -669,6 +715,16 @@ func (c *Consortium) signerInTurn(signer common.Address, number uint64, validato return validators[index] == signer } +func (c *Consortium) initContract() error { + contract, err := consortiumCommon.NewContractIntegrator(c.chainConfig, c.ethAPI) + if err != nil { + return err + } + c.contract = contract + + return nil +} + // ecrecover extracts the Ethereum account address from a signed header. func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) { // If the signature's already cached, return that diff --git a/consensus/consortium/v2/abi.go b/consensus/consortium/v2/abi.go deleted file mode 100644 index 75198df70d..0000000000 --- a/consensus/consortium/v2/abi.go +++ /dev/null @@ -1,5 +0,0 @@ -package v2 - -const validatorSetABI = `` - -const slashABI = `` diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index 7161162050..3bc2cc15fc 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -4,14 +4,11 @@ import ( "bytes" "errors" "fmt" - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" consortiumCommon "github.com/ethereum/go-ethereum/consensus/consortium/common" "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/systemcontracts" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" @@ -26,7 +23,6 @@ import ( "io" "math/big" "sort" - "strings" "sync" "time" ) @@ -80,19 +76,6 @@ var ( errMismatchingEpochValidators = errors.New("mismatching validator list on epoch block") ) -var ( - systemContracts = map[common.Address]bool{ - common.HexToAddress(systemcontracts.ValidatorContract): true, - common.HexToAddress(systemcontracts.SlashContract): true, - } -) - -type SignerTxFn func(accounts.Account, *types.Transaction, *big.Int) (*types.Transaction, error) - -func isToSystemContract(to common.Address) bool { - return systemContracts[to] -} - type Consortium struct { chainConfig *params.ChainConfig config *params.ConsortiumConfig // Consensus engine configuration parameters @@ -105,13 +88,13 @@ type Consortium struct { val common.Address // Ethereum address of the signing key signer types.Signer signFn consortiumCommon.SignerFn // Signer function to authorize hashes with - signTxFn SignerTxFn + signTxFn consortiumCommon.SignerTxFn lock sync.RWMutex // Protects the signer fields - ethAPI *ethapi.PublicBlockChainAPI - validatorSetABI abi.ABI - slashABI abi.ABI + ethAPI *ethapi.PublicBlockChainAPI + statedb *state.StateDB + contract *consortiumCommon.ContractIntegrator fakeDiff bool } @@ -131,20 +114,16 @@ func New( // Allocate the snapshot caches and create the engine recents, _ := lru.NewARC(inmemorySnapshots) signatures, _ := lru.NewARC(inmemorySignatures) - vABI, _ := abi.JSON(strings.NewReader(validatorSetABI)) - sABI, _ := abi.JSON(strings.NewReader(slashABI)) return &Consortium{ - chainConfig: chainConfig, - config: consortiumConfig, - genesisHash: genesisHash, - db: db, - ethAPI: ethAPI, - recents: recents, - signatures: signatures, - validatorSetABI: vABI, - slashABI: sABI, - signer: types.NewEIP155Signer(chainConfig.ChainID), + chainConfig: chainConfig, + config: consortiumConfig, + genesisHash: genesisHash, + db: db, + ethAPI: ethAPI, + recents: recents, + signatures: signatures, + signer: types.NewEIP155Signer(chainConfig.ChainID), } } @@ -157,7 +136,7 @@ func (c *Consortium) IsSystemTransaction(tx *types.Transaction, header *types.He if err != nil { return false, errors.New("UnAuthorized transaction") } - if sender == header.Coinbase && isToSystemContract(*tx.To()) && tx.GasPrice().Cmp(big.NewInt(0)) == 0 { + if sender == header.Coinbase && c.IsSystemContract(tx.To()) && tx.GasPrice().Cmp(big.NewInt(0)) == 0 { return true, nil } return false, nil @@ -167,7 +146,7 @@ func (c *Consortium) IsSystemContract(to *common.Address) bool { if to == nil { return false } - return isToSystemContract(*to) + return c.chainConfig.ConsortiumV2Contracts.IsSystemContract(*to) } func (c *Consortium) EnoughDistance(chain consensus.ChainReader, header *types.Header) bool { @@ -473,6 +452,10 @@ func (c *Consortium) verifySeal(chain consensus.ChainHeaderReader, header *types } func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { + if err := c.initContract(); err != nil { + return err + } + header.Coinbase = c.val header.Nonce = types.BlockNonce{} @@ -492,7 +475,7 @@ func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.He header.Extra = header.Extra[:extraVanity] if number%c.config.Epoch == 0 { - newValidators, err := c.getCurrentValidators(header.ParentHash, new(big.Int).Sub(header.Number, common.Big1)) + newValidators, err := c.contract.GetValidators(header) if err != nil { return err } @@ -523,6 +506,9 @@ func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.He func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs *[]*types.Transaction, uncles []*types.Header, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction, usedGas *uint64) error { + if err := c.initContract(); err != nil { + return err + } // warn if not in majority fork number := header.Number.Uint64() snap, err := c.snapshot(chain, number-1, header.ParentHash, nil) @@ -530,10 +516,27 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H return err } + transactOpts := &consortiumCommon.ApplyTransactOpts{ + ApplyMessageOpts: &consortiumCommon.ApplyMessageOpts{ + State: state, + Header: header, + ChainConfig: c.chainConfig, + ChainContext: consortiumCommon.ChainContext{Chain: chain, Consortium: c}, + }, + Txs: txs, + Receipts: receipts, + ReceivedTxs: systemTxs, + UsedGas: usedGas, + Mining: false, + Signer: c.signer, + SignTxFn: c.signTxFn, + EthAPI: c.ethAPI, + } + // If the block is a epoch end block, verify the validator list // The verification can only be done when the state is ready, it can't be done in VerifyHeader. if header.Number.Uint64()%c.config.Epoch == 0 { - newValidators, err := c.getCurrentValidators(header.ParentHash, new(big.Int).Sub(header.Number, common.Big1)) + newValidators, err := c.contract.GetValidators(header) if err != nil { return err } @@ -550,7 +553,6 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H } } // No block rewards in PoA, so the state remains as is and uncles are dropped - cx := chainContext{Chain: chain, consortium: c} if header.Difficulty.Cmp(diffInTurn) != 0 { spoiledVal := snap.supposeValidator() signedRecently := false @@ -562,15 +564,14 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H } if !signedRecently { log.Trace("slash validator", "block hash", header.Hash(), "address", spoiledVal) - err = c.slash(spoiledVal, state, header, cx, txs, receipts, systemTxs, usedGas, false) + err = c.contract.Slash(spoiledVal, transactOpts) if err != nil { // it is possible that slash validator failed because of the slash channel is disabled. log.Error("slash validator failed", "block hash", header.Hash(), "address", spoiledVal) } } } - val := header.Coinbase - err = c.distributeIncoming(val, state, header, cx, txs, receipts, systemTxs, usedGas, false) + err = c.contract.DistributeRewards(c.val, transactOpts) if err != nil { return err } @@ -582,8 +583,11 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { + if err := c.initContract(); err != nil { + return nil, err + } + // No block rewards in PoA, so the state remains as is and uncles are dropped - cx := chainContext{Chain: chain, consortium: c} if txs == nil { txs = make([]*types.Transaction, 0) } @@ -591,6 +595,21 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head receipts = make([]*types.Receipt, 0) } + transactOpts := &consortiumCommon.ApplyTransactOpts{ + ApplyMessageOpts: &consortiumCommon.ApplyMessageOpts{ + State: state, + Header: header, + ChainConfig: c.chainConfig, + ChainContext: consortiumCommon.ChainContext{Chain: chain, Consortium: c}, + }, + Txs: &txs, + Receipts: &receipts, + ReceivedTxs: nil, + UsedGas: &header.GasUsed, + Mining: true, + Signer: c.signer, + SignTxFn: c.signTxFn, + } if header.Difficulty.Cmp(diffInTurn) != 0 { number := header.Number.Uint64() snap, err := c.snapshot(chain, number-1, header.ParentHash, nil) @@ -606,14 +625,21 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head } } if !signedRecently { - err = c.slash(spoiledVal, state, header, cx, &txs, &receipts, nil, &header.GasUsed, true) + err = c.contract.Slash(spoiledVal, transactOpts) if err != nil { // it is possible that slash validator failed because of the slash channel is disabled. log.Error("slash validator failed", "block hash", header.Hash(), "address", spoiledVal) } } } - err := c.distributeIncoming(c.val, state, header, cx, &txs, &receipts, nil, &header.GasUsed, true) + + if c.chainConfig.IsOnConsortiumV2(header.Number.Add(header.Number, common.Big1)) { + if err := c.contract.UpdateValidators(header, transactOpts); err != nil { + log.Error("Failed to update validators: ", err) + } + } + + err := c.contract.DistributeRewards(c.val, transactOpts) if err != nil { return nil, err } @@ -640,6 +666,15 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head return blk, nil } +func (c *Consortium) Authorize(signer common.Address, signFn consortiumCommon.SignerFn, signTxFn consortiumCommon.SignerTxFn) { + c.lock.Lock() + defer c.lock.Unlock() + + c.val = signer + c.signFn = signFn + c.signTxFn = signTxFn +} + func (c *Consortium) Delay(chain consensus.ChainReader, header *types.Header) *time.Duration { return nil } @@ -679,6 +714,16 @@ func (c *Consortium) getValidatorsFromHeader(header *types.Header) []common.Addr return consortiumCommon.ExtractAddressFromBytes(header.Extra[extraVanity:extraSuffix]) } +func (c *Consortium) initContract() error { + contract, err := consortiumCommon.NewContractIntegrator(c.chainConfig, c.ethAPI) + if err != nil { + return err + } + c.contract = contract + + return nil +} + // ecrecover extracts the Ethereum account address from a signed header. func ecrecover(header *types.Header, sigcache *lru.ARCCache, chainId *big.Int) (common.Address, error) { // If the signature's already cached, return that diff --git a/consensus/consortium/v2/contract.go b/consensus/consortium/v2/contract.go deleted file mode 100644 index aac01acc61..0000000000 --- a/consensus/consortium/v2/contract.go +++ /dev/null @@ -1,304 +0,0 @@ -package v2 - -import ( - "bytes" - "context" - "encoding/hex" - "errors" - "fmt" - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/systemcontracts" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/internal/ethapi" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" - "math" - "math/big" -) - -// Interaction with contract/account -func (c *Consortium) getCurrentValidators(blockHash common.Hash, blockNumber *big.Int) ([]common.Address, error) { - blockNr := rpc.BlockNumberOrHashWithHash(blockHash, false) - method := "getValidators" - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() // cancel when we are finished consuming integers - - data, err := c.validatorSetABI.Pack(method) - if err != nil { - log.Error("Unable to pack tx for getValidators", "error", err) - return nil, err - } - - // call - msgData := (hexutil.Bytes)(data) - toAddress := common.HexToAddress(systemcontracts.ValidatorContract) - gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2)) - result, err := c.ethAPI.Call(ctx, ethapi.TransactionArgs{ - Gas: &gas, - To: &toAddress, - Data: &msgData, - }, blockNr, nil) - if err != nil { - return nil, err - } - - var ( - ret0 = new([]common.Address) - ) - out := ret0 - - if err := c.validatorSetABI.UnpackIntoInterface(out, method, result); err != nil { - return nil, err - } - - valz := make([]common.Address, len(*ret0)) - for i, a := range *ret0 { - valz[i] = a - } - return valz, nil -} - -// slash spoiled validators -func (c *Consortium) distributeIncoming( - val common.Address, - state *state.StateDB, - header *types.Header, - chain core.ChainContext, - txs *[]*types.Transaction, - receipts *[]*types.Receipt, - receivedTxs *[]*types.Transaction, - usedGas *uint64, - mining bool, -) error { - coinbase := header.Coinbase - balance := state.GetBalance(consensus.SystemAddress) - if balance.Cmp(common.Big0) <= 0 { - return nil - } - state.SetBalance(consensus.SystemAddress, big.NewInt(0)) - state.AddBalance(coinbase, balance) - - log.Trace("distribute to validator contract", "block hash", header.Hash(), "amount", balance) - return c.distributeToValidator(balance, val, state, header, chain, txs, receipts, receivedTxs, usedGas, mining) -} - -// slash spoiled validators -func (c *Consortium) slash(spoiledVal common.Address, state *state.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error { - // method - method := "slash" - - // get packed data - data, err := c.slashABI.Pack(method, - spoiledVal, - ) - if err != nil { - log.Error("Unable to pack tx for slash", "error", err) - return err - } - // get system message - msg := c.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.SlashContract), data, common.Big0) - // apply message - return c.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining) -} - -func (c *Consortium) initContract( - state *state.StateDB, - header *types.Header, - chain core.ChainContext, - txs *[]*types.Transaction, - receipts *[]*types.Receipt, - receivedTxs *[]*types.Transaction, - usedGas *uint64, - mining bool, -) error { - // method - method := "init" - // contracts - contracts := []string{ - systemcontracts.ValidatorContract, - systemcontracts.SlashContract, - } - // get packed data - data, err := c.validatorSetABI.Pack(method) - if err != nil { - log.Error("Unable to pack tx for init validator set", "error", err) - return err - } - for _, contract := range contracts { - msg := c.getSystemMessage(header.Coinbase, common.HexToAddress(contract), data, common.Big0) - // apply message - log.Trace("init contract", "block hash", header.Hash(), "contract", contract) - err = c.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining) - if err != nil { - return err - } - } - return nil -} - -// slash spoiled validators -func (c *Consortium) distributeToValidator( - amount *big.Int, - validator common.Address, - state *state.StateDB, - header *types.Header, - chain core.ChainContext, - txs *[]*types.Transaction, - receipts *[]*types.Receipt, - receivedTxs *[]*types.Transaction, - usedGas *uint64, - mining bool, -) error { - // method - method := "deposit" - - // get packed data - data, err := c.validatorSetABI.Pack(method, - validator, - ) - if err != nil { - log.Error("Unable to pack tx for deposit", "error", err) - return err - } - // get system message - msg := c.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.ValidatorContract), data, amount) - // apply message - return c.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining) -} - -func (c *Consortium) getSystemMessage(from, toAddress common.Address, data []byte, value *big.Int) callmsg { - return callmsg{ - ethereum.CallMsg{ - From: from, - Gas: math.MaxUint64 / 2, - GasPrice: big.NewInt(0), - Value: value, - To: &toAddress, - Data: data, - }, - } -} - -func (c *Consortium) applyTransaction( - msg callmsg, - state *state.StateDB, - header *types.Header, - chainContext core.ChainContext, - txs *[]*types.Transaction, - receipts *[]*types.Receipt, - receivedTxs *[]*types.Transaction, - usedGas *uint64, - mining bool, -) (err error) { - nonce := state.GetNonce(msg.From()) - expectedTx := types.NewTransaction(nonce, *msg.To(), msg.Value(), msg.Gas(), msg.GasPrice(), msg.Data()) - expectedHash := c.signer.Hash(expectedTx) - - if msg.From() == c.val && mining { - expectedTx, err = c.signTxFn(accounts.Account{Address: msg.From()}, expectedTx, c.chainConfig.ChainID) - if err != nil { - return err - } - } else { - if receivedTxs == nil || len(*receivedTxs) == 0 || (*receivedTxs)[0] == nil { - return errors.New("supposed to get a actual transaction, but get none") - } - actualTx := (*receivedTxs)[0] - if !bytes.Equal(c.signer.Hash(actualTx).Bytes(), expectedHash.Bytes()) { - return fmt.Errorf("expected tx hash %v, get %v, nonce %d, to %s, value %s, gas %d, gasPrice %s, data %s", expectedHash.String(), actualTx.Hash().String(), - expectedTx.Nonce(), - expectedTx.To().String(), - expectedTx.Value().String(), - expectedTx.Gas(), - expectedTx.GasPrice().String(), - hex.EncodeToString(expectedTx.Data()), - ) - } - expectedTx = actualTx - // move to next - *receivedTxs = (*receivedTxs)[1:] - } - state.Prepare(expectedTx.Hash(), len(*txs)) - gasUsed, err := applyMessage(msg, state, header, c.chainConfig, chainContext) - if err != nil { - return err - } - *txs = append(*txs, expectedTx) - var root []byte - if c.chainConfig.IsByzantium(header.Number) { - state.Finalise(true) - } else { - root = state.IntermediateRoot(c.chainConfig.IsEIP158(header.Number)).Bytes() - } - *usedGas += gasUsed - receipt := types.NewReceipt(root, false, *usedGas) - receipt.TxHash = expectedTx.Hash() - receipt.GasUsed = gasUsed - - // Set the receipt logs and create a bloom for filtering - receipt.Logs = state.GetLogs(expectedTx.Hash(), header.Hash()) - receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) - receipt.BlockHash = header.Hash() - receipt.BlockNumber = header.Number - receipt.TransactionIndex = uint(state.TxIndex()) - *receipts = append(*receipts, receipt) - state.SetNonce(msg.From(), nonce+1) - return nil -} - -func applyMessage( - msg callmsg, - state *state.StateDB, - header *types.Header, - chainConfig *params.ChainConfig, - chainContext core.ChainContext, -) (uint64, error) { - // Create a new context to be used in the EVM environment - context := core.NewEVMBlockContext(header, chainContext, nil) - // Create a new environment which holds all relevant information - // about the transaction and calling mechanisms. - vmenv := vm.NewEVM(context, vm.TxContext{Origin: msg.From(), GasPrice: big.NewInt(0)}, state, chainConfig, vm.Config{}) - // Apply the transaction to the current state (included in the env) - ret, returnGas, err := vmenv.Call( - vm.AccountRef(msg.From()), - *msg.To(), - msg.Data(), - msg.Gas(), - msg.Value(), - ) - if err != nil { - log.Error("apply message failed", "msg", string(ret), "err", err) - } - return msg.Gas() - returnGas, err -} - -// callmsg implements core.Message to allow passing it as a transaction simulator. -type callmsg struct { - ethereum.CallMsg -} - -func (m callmsg) From() common.Address { return m.CallMsg.From } - -func (m callmsg) Nonce() uint64 { return 0 } - -func (m callmsg) CheckNonce() bool { return false } - -func (m callmsg) To() *common.Address { return m.CallMsg.To } - -func (m callmsg) GasPrice() *big.Int { return m.CallMsg.GasPrice } - -func (m callmsg) Gas() uint64 { return m.CallMsg.Gas } - -func (m callmsg) Value() *big.Int { return m.CallMsg.Value } - -func (m callmsg) Data() []byte { return m.CallMsg.Data } diff --git a/core/state_transition.go b/core/state_transition.go index 135a9c6dbe..bc37b07a23 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -18,6 +18,7 @@ package core import ( "fmt" + "github.com/ethereum/go-ethereum/consensus" "math" "math/big" @@ -332,11 +333,19 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) { // After EIP-3529: refunds are capped to gasUsed / 5 st.refundGas(params.RefundQuotientEIP3529) } + effectiveTip := st.gasPrice if london { effectiveTip = cmath.BigMin(st.gasTipCap, new(big.Int).Sub(st.gasFeeCap, st.evm.Context.BaseFee)) } - st.state.AddBalance(st.evm.Context.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), effectiveTip)) + + // if currentBlock is ConsortiumV2 then add balance to system address + newEffectiveTip := new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), effectiveTip) + if st.evm.ChainConfig().IsConsortiumV2(st.evm.Context.BlockNumber) { + st.state.AddBalance(consensus.SystemAddress, newEffectiveTip) + } else { + st.state.AddBalance(st.evm.Context.Coinbase, newEffectiveTip) + } return &ExecutionResult{ UsedGas: st.gasUsed(), diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 5278550aa3..57c29443ed 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -727,6 +727,10 @@ func (s *PublicBlockChainAPI) GetHeaderByNumber(ctx context.Context, number rpc. return nil, err } +func (s *PublicBlockChainAPI) GetHeader(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) { + return s.b.HeaderByNumber(ctx, number) +} + // GetHeaderByHash returns the requested header by hash. func (s *PublicBlockChainAPI) GetHeaderByHash(ctx context.Context, hash common.Hash) map[string]interface{} { header, _ := s.b.HeaderByHash(ctx, hash) diff --git a/params/config.go b/params/config.go index 7ad1cb659a..2a34c513d5 100644 --- a/params/config.go +++ b/params/config.go @@ -20,6 +20,7 @@ import ( "encoding/binary" "fmt" "math/big" + "reflect" "github.com/ethereum/go-ethereum/common" "golang.org/x/crypto/sha3" @@ -281,16 +282,16 @@ var ( // // This configuration is intentionally not using keyed fields to force anyone // adding flags to the config to also have to set these fields. - AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, nil, new(EthashConfig), nil, nil} + AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, nil, new(EthashConfig), nil, nil, nil} // AllCliqueProtocolChanges contains every protocol change (EIPs) introduced // and accepted by the Ethereum core developers into the Clique consensus. // // This configuration is intentionally not using keyed fields to force anyone // adding flags to the config to also have to set these fields. - AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil} + AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil, nil} - TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, nil, new(EthashConfig), nil, nil} + TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, nil, new(EthashConfig), nil, nil, nil} TestRules = TestChainConfig.Rules(new(big.Int)) ) @@ -382,9 +383,10 @@ type ChainConfig struct { TerminalTotalDifficulty *big.Int `json:"terminalTotalDifficulty,omitempty"` // Various consensus engines - Ethash *EthashConfig `json:"ethash,omitempty"` - Clique *CliqueConfig `json:"clique,omitempty"` - Consortium *ConsortiumConfig `json:"consortium,omitempty"` + Ethash *EthashConfig `json:"ethash,omitempty"` + Clique *CliqueConfig `json:"clique,omitempty"` + Consortium *ConsortiumConfig `json:"consortium,omitempty"` + ConsortiumV2Contracts *ConsortiumV2Contracts `json:"consortiumV2Contracts"` } // EthashConfig is the consensus engine configs for proof-of-work based sealing. @@ -417,6 +419,21 @@ func (c *ConsortiumConfig) String() string { return "consortium" } +type ConsortiumV2Contracts struct { + ValidatorSC common.Address `json:"validatorSC"` +} + +func (c *ConsortiumV2Contracts) IsSystemContract(address common.Address) bool { + e := reflect.ValueOf(c).Elem() + for i := 0; i < e.NumField(); i++ { + if e.Field(i).Interface().(common.Address) == address { + return true + } + } + + return false +} + // String implements the fmt.Stringer interface. func (c *ChainConfig) String() string { var engine interface{} From 284a08d53c24c36581c4eae7362321e30ed7cc70 Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Sun, 21 Aug 2022 14:19:57 +0700 Subject: [PATCH 13/52] Fix: add update validators to `finalize` method (#106) * fix: Add updateValidators to `Finalize` method to make sure `updateValidators` transaction is processed in received sides * fix: wrong validation when calling updateValidations --- consensus/consortium/v2/consortium.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index 3bc2cc15fc..630ed28c01 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -571,6 +571,13 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H } } } + + if header.Number.Uint64()%c.config.Epoch == c.config.Epoch-1 { + if err := c.contract.UpdateValidators(header, transactOpts); err != nil { + log.Error("Failed to update validators: ", err) + } + } + err = c.contract.DistributeRewards(c.val, transactOpts) if err != nil { return err @@ -633,7 +640,7 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head } } - if c.chainConfig.IsOnConsortiumV2(header.Number.Add(header.Number, common.Big1)) { + if header.Number.Uint64()%c.config.Epoch == c.config.Epoch-1 { if err := c.contract.UpdateValidators(header, transactOpts); err != nil { log.Error("Failed to update validators: ", err) } From 38e4cf78c5d77a9e6532552d61bffda2e448af14 Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Sun, 21 Aug 2022 17:00:04 +0700 Subject: [PATCH 14/52] fix: update validators generated code (#107) - Add `addNode` function to support adding new nodes - Change NewContractIntegrator param from `*ConsortiumBackend` to `bind.ContractBackend` interface to make it more flexible (we can adapt different backends lately) --- consensus/consortium/common/contract.go | 10 ++++---- consensus/consortium/v1/consortium.go | 2 +- consensus/consortium/v2/consortium.go | 2 +- .../generated_contracts/validators/main.go | 23 ++++++++++++++++++- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/consensus/consortium/common/contract.go b/consensus/consortium/common/contract.go index d47c5aa923..1878bd4ff6 100644 --- a/consensus/consortium/common/contract.go +++ b/consensus/consortium/common/contract.go @@ -32,10 +32,8 @@ type ContractIntegrator struct { validatorSC *validators.Validators } -func NewContractIntegrator(config *chainParams.ChainConfig, ee *ethapi.PublicBlockChainAPI) (*ContractIntegrator, error) { - backend := NewConsortiumBackend(ee) - - validatorSC, err := validators.NewValidators(config.ConsortiumV2Contracts.ValidatorSC, &backend) +func NewContractIntegrator(config *chainParams.ChainConfig, backend bind.ContractBackend) (*ContractIntegrator, error) { + validatorSC, err := validators.NewValidators(config.ConsortiumV2Contracts.ValidatorSC, backend) if err != nil { return nil, err } @@ -239,8 +237,8 @@ type ConsortiumBackend struct { ee *ethapi.PublicBlockChainAPI } -func NewConsortiumBackend(ee *ethapi.PublicBlockChainAPI) ConsortiumBackend { - return ConsortiumBackend{ +func NewConsortiumBackend(ee *ethapi.PublicBlockChainAPI) *ConsortiumBackend { + return &ConsortiumBackend{ ee, } } diff --git a/consensus/consortium/v1/consortium.go b/consensus/consortium/v1/consortium.go index f96516c792..032c33e76e 100644 --- a/consensus/consortium/v1/consortium.go +++ b/consensus/consortium/v1/consortium.go @@ -716,7 +716,7 @@ func (c *Consortium) signerInTurn(signer common.Address, number uint64, validato } func (c *Consortium) initContract() error { - contract, err := consortiumCommon.NewContractIntegrator(c.chainConfig, c.ethAPI) + contract, err := consortiumCommon.NewContractIntegrator(c.chainConfig, consortiumCommon.NewConsortiumBackend(c.ethAPI)) if err != nil { return err } diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index 630ed28c01..ebfc53f27f 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -722,7 +722,7 @@ func (c *Consortium) getValidatorsFromHeader(header *types.Header) []common.Addr } func (c *Consortium) initContract() error { - contract, err := consortiumCommon.NewContractIntegrator(c.chainConfig, c.ethAPI) + contract, err := consortiumCommon.NewContractIntegrator(c.chainConfig, consortiumCommon.NewConsortiumBackend(c.ethAPI)) if err != nil { return err } diff --git a/core/systemcontracts/generated_contracts/validators/main.go b/core/systemcontracts/generated_contracts/validators/main.go index 4b3b5e8512..ca32c4099b 100644 --- a/core/systemcontracts/generated_contracts/validators/main.go +++ b/core/systemcontracts/generated_contracts/validators/main.go @@ -30,7 +30,7 @@ var ( // ValidatorsMetaData contains all meta data concerning the Validators contract. var ValidatorsMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"currentValidatorSet\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"consensusAddress\",\"type\":\"address\"},{\"internalType\":\"addresspayable\",\"name\":\"feeAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jailTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reward\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"currentValidatorSetMap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"valAddr\",\"type\":\"address\"}],\"name\":\"depositReward\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastUpdated\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getValidators\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateValidators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"consensusAddress\",\"type\":\"address\"},{\"internalType\":\"addresspayable\",\"name\":\"feeAddress\",\"type\":\"address\"}],\"name\":\"addNode\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"currentValidatorSet\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"consensusAddress\",\"type\":\"address\"},{\"internalType\":\"addresspayable\",\"name\":\"feeAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jailTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reward\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"currentValidatorSetMap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"valAddr\",\"type\":\"address\"}],\"name\":\"depositReward\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastUpdated\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getValidators\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateValidators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", } // ValidatorsABI is the input ABI used to generate the binding from. @@ -332,6 +332,27 @@ func (_Validators *ValidatorsCallerSession) GetValidators() ([]common.Address, e return _Validators.Contract.GetValidators(&_Validators.CallOpts) } +// AddNode is a paid mutator transaction binding the contract method 0xdb8ec38c. +// +// Solidity: function addNode(address consensusAddress, address feeAddress) returns() +func (_Validators *ValidatorsTransactor) AddNode(opts *bind.TransactOpts, consensusAddress common.Address, feeAddress common.Address) (*types.Transaction, error) { + return _Validators.contract.Transact(opts, "addNode", consensusAddress, feeAddress) +} + +// AddNode is a paid mutator transaction binding the contract method 0xdb8ec38c. +// +// Solidity: function addNode(address consensusAddress, address feeAddress) returns() +func (_Validators *ValidatorsSession) AddNode(consensusAddress common.Address, feeAddress common.Address) (*types.Transaction, error) { + return _Validators.Contract.AddNode(&_Validators.TransactOpts, consensusAddress, feeAddress) +} + +// AddNode is a paid mutator transaction binding the contract method 0xdb8ec38c. +// +// Solidity: function addNode(address consensusAddress, address feeAddress) returns() +func (_Validators *ValidatorsTransactorSession) AddNode(consensusAddress common.Address, feeAddress common.Address) (*types.Transaction, error) { + return _Validators.Contract.AddNode(&_Validators.TransactOpts, consensusAddress, feeAddress) +} + // DepositReward is a paid mutator transaction binding the contract method 0x6ffa4dc1. // // Solidity: function depositReward(address valAddr) payable returns() From 9c045abc7d8170fdde3937349bcc62a90c5f80fb Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Sun, 21 Aug 2022 17:00:22 +0700 Subject: [PATCH 15/52] fix: Add missing signTx params when calling `consortium.Authorize` on miner (#108) --- eth/backend.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eth/backend.go b/eth/backend.go index ff492e0d0b..f56b3a50a4 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -509,7 +509,7 @@ func (s *Ethereum) StartMining(threads int) error { log.Error("Etherbase account unavailable locally", "err", err) return fmt.Errorf("signer missing: %v", err) } - consortium.Authorize(eb, wallet.SignData) + consortium.Authorize(eb, wallet.SignData, wallet.SignTx) } // If mining is started, we can disable the transaction rejection mechanism // introduced to speed sync times. From e5b4e18c12579e16f1b7274c8e37e59fb3919622 Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Mon, 22 Aug 2022 10:29:23 +0700 Subject: [PATCH 16/52] Fix pointer issue validating end of v1 (#109) * fix: worker starts before getValidatorsSC is set * fix: call `SetGetSCValidatorsFn` instead of `SetGetFenixValidators` in `Consortium.SetGetSCValidatorsFn` * fix: pointer issue when validating current block is end of v1 or not --- consensus/consortium/main.go | 2 +- consensus/consortium/v1/consortium.go | 13 ++++---- eth/backend.go | 46 +++++++++++++-------------- miner/worker.go | 2 +- 4 files changed, 32 insertions(+), 31 deletions(-) diff --git a/consensus/consortium/main.go b/consensus/consortium/main.go index ba265e4900..5b8af8130f 100644 --- a/consensus/consortium/main.go +++ b/consensus/consortium/main.go @@ -162,7 +162,7 @@ func (c *Consortium) Authorize(signer common.Address, signFn consortiumCommon.Si // SetGetSCValidatorsFn backward compatible for consortium v1 func (c *Consortium) SetGetSCValidatorsFn(fn func() ([]common.Address, error)) { - c.v1.SetGetFenixValidators(fn) + c.v1.SetGetSCValidatorsFn(fn) } // SetGetFenixValidators backward compatible for consortium v1 diff --git a/consensus/consortium/v1/consortium.go b/consensus/consortium/v1/consortium.go index 032c33e76e..ac85260699 100644 --- a/consensus/consortium/v1/consortium.go +++ b/consensus/consortium/v1/consortium.go @@ -505,7 +505,7 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) header.UncleHash = types.CalcUncleHash(nil) - if c.chainConfig.IsOnConsortiumV2(header.Number.Add(header.Number, common.Big1)) { + if c.chainConfig.IsOnConsortiumV2(big.NewInt(header.Number.Int64() + 1)) { transactOpts := &consortiumCommon.ApplyTransactOpts{ ApplyMessageOpts: &consortiumCommon.ApplyMessageOpts{ State: state, @@ -716,12 +716,13 @@ func (c *Consortium) signerInTurn(signer common.Address, number uint64, validato } func (c *Consortium) initContract() error { - contract, err := consortiumCommon.NewContractIntegrator(c.chainConfig, consortiumCommon.NewConsortiumBackend(c.ethAPI)) - if err != nil { - return err + if c.chainConfig.ConsortiumV2Block != nil && c.chainConfig.ConsortiumV2Contracts != nil { + contract, err := consortiumCommon.NewContractIntegrator(c.chainConfig, consortiumCommon.NewConsortiumBackend(c.ethAPI)) + if err != nil { + return err + } + c.contract = contract } - c.contract = contract - return nil } diff --git a/eth/backend.go b/eth/backend.go index f56b3a50a4..87642cecf8 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -21,14 +21,13 @@ import ( "errors" "fmt" "github.com/ethereum/go-ethereum/consensus/consortium" + "github.com/ethereum/go-ethereum/core/state" "math/big" "runtime" "sync" "sync/atomic" "time" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -234,6 +233,28 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { return nil, err } + // set SCValidators function before initiating new miner to prevent miner starts without SCValidators + if chainConfig.Consortium != nil { + c := eth.engine.(*consortium.Consortium) + stack.RegisterAPIs(c.APIs(eth.blockchain)) + c.SetGetSCValidatorsFn(func() ([]common.Address, error) { + stateDb, err := eth.blockchain.State() + if err != nil { + log.Crit("Cannot get state of blockchain", "err", err) + return nil, err + } + return state.GetSCValidators(stateDb), nil + }) + c.SetGetFenixValidators(func() ([]common.Address, error) { + stateDb, err := eth.blockchain.State() + if err != nil { + log.Crit("Cannot get state of blockchain", "err", err) + return nil, err + } + return state.GetFenixValidators(stateDb, eth.blockchain.Config().FenixValidatorContractAddress), nil + }) + } + eth.miner = miner.New(eth, &config.Miner, chainConfig, eth.EventMux(), eth.engine, eth.isLocalBlock) eth.miner.SetExtra(makeExtraData(config.Miner.ExtraData)) @@ -278,27 +299,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { "age", common.PrettyAge(t)) } } - - if chainConfig.Consortium != nil { - c := eth.engine.(*consortium.Consortium) - stack.RegisterAPIs(c.APIs(eth.blockchain)) - c.SetGetSCValidatorsFn(func() ([]common.Address, error) { - stateDb, err := eth.blockchain.State() - if err != nil { - log.Crit("Cannot get state of blockchain", "err", err) - return nil, err - } - return state.GetSCValidators(stateDb), nil - }) - c.SetGetFenixValidators(func() ([]common.Address, error) { - stateDb, err := eth.blockchain.State() - if err != nil { - log.Crit("Cannot get state of blockchain", "err", err) - return nil, err - } - return state.GetFenixValidators(stateDb, eth.blockchain.Config().FenixValidatorContractAddress), nil - }) - } return eth, nil } diff --git a/miner/worker.go b/miner/worker.go index 4631dd1ce1..34c1500f42 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -593,7 +593,7 @@ func (w *worker) taskLoop() { w.pendingMu.Unlock() if err := w.engine.Seal(w.chain, task.block, w.resultCh, stopCh); err != nil { - log.Warn("Block sealing failed", "err", err) + log.Warn("Block sealing failed", "err", err, "height", task.block.NumberU64()) w.pendingMu.Lock() delete(w.pendingTasks, sealHash) w.pendingMu.Unlock() From 4a5025308809a0dc1c1e3e38a1a96c76e63d5ed7 Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Tue, 23 Aug 2022 15:21:33 +0700 Subject: [PATCH 17/52] feat: implement Seal method (#111) --- accounts/accounts.go | 1 + consensus/consortium/v2/consortium.go | 77 +++++++++++++++++++++ consensus/consortium/v2/consortiumv2fork.go | 20 ++++++ 3 files changed, 98 insertions(+) diff --git a/accounts/accounts.go b/accounts/accounts.go index 7178578091..53de79fcad 100644 --- a/accounts/accounts.go +++ b/accounts/accounts.go @@ -39,6 +39,7 @@ const ( MimetypeDataWithValidator = "data/validator" MimetypeTypedData = "data/typed" MimetypeClique = "application/x-clique-header" + MimetypeConsortium = "application/x-clique-header" MimetypeTextPlain = "text/plain" ) diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index ebfc53f27f..cd16b28989 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -4,6 +4,7 @@ import ( "bytes" "errors" "fmt" + "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" consortiumCommon "github.com/ethereum/go-ethereum/consensus/consortium/common" @@ -687,6 +688,82 @@ func (c *Consortium) Delay(chain consensus.ChainReader, header *types.Header) *t } func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { + header := block.Header() + + // Sealing the genesis block is not supported + number := header.Number.Uint64() + if number == 0 { + return consortiumCommon.ErrUnknownBlock + } + // For 0-period chains, refuse to seal empty blocks (no reward but would spin sealing) + if c.config.Period == 0 && len(block.Transactions()) == 0 { + log.Info("Sealing paused, waiting for transactions") + return nil + } + // Don't hold the val fields for the entire sealing procedure + c.lock.RLock() + val, signFn := c.val, c.signFn + c.lock.RUnlock() + + snap, err := c.snapshot(chain, number-1, header.ParentHash, nil) + if err != nil { + return err + } + + // Bail out if we're unauthorized to sign a block + if _, authorized := snap.Validators[val]; !authorized { + return errUnauthorizedValidator + } + + // If we're amongst the recent signers, wait for the next block + for seen, recent := range snap.Recents { + if recent == val { + // Signer is among recents, only wait if the current block doesn't shift it out + if limit := uint64(len(snap.Validators)/2 + 1); number < limit || seen > number-limit { + log.Info("Signed recently, must wait for others") + return nil + } + } + } + + // Sweet, the protocol permits us to sign the block, wait for our time + delay := c.delayForConsortiumV2Fork(snap, header) + + log.Info("Sealing block with", "number", number, "delay", delay, "headerDifficulty", header.Difficulty, "val", val.Hex()) + + // Sign all the things! + sig, err := signFn(accounts.Account{Address: val}, accounts.MimetypeConsortium, consortiumRLP(header, c.chainConfig.ChainID)) + if err != nil { + return err + } + copy(header.Extra[len(header.Extra)-extraSeal:], sig) + + // Wait until sealing is terminated or delay timeout. + log.Trace("Waiting for slot to sign and propagate", "delay", common.PrettyDuration(delay)) + go func() { + select { + case <-stop: + return + case <-time.After(delay): + } + //if c.shouldWaitForCurrentBlockProcess(chain, header, snap) { + // log.Info("Waiting for received in turn block to process") + // select { + // case <-stop: + // log.Info("Received block process finished, abort block seal") + // return + // case <-time.After(time.Duration(processBackOffTime) * time.Second): + // log.Info("Process backoff time exhausted, start to seal block") + // } + //} + + select { + case results <- block.WithSeal(header): + default: + log.Warn("Sealing result is not read by miner", "sealhash", SealHash(header, c.chainConfig.ChainID)) + } + }() + return nil } diff --git a/consensus/consortium/v2/consortiumv2fork.go b/consensus/consortium/v2/consortiumv2fork.go index 4986eda3d2..cfb771b43b 100644 --- a/consensus/consortium/v2/consortiumv2fork.go +++ b/consensus/consortium/v2/consortiumv2fork.go @@ -2,8 +2,28 @@ package v2 import ( "github.com/ethereum/go-ethereum/core/types" + "math/rand" + "time" ) +const ( + wiggleTimeBeforeFork = 500 * time.Millisecond // Random delay (per signer) to allow concurrent signers + fixedBackOffTimeBeforeFork = 200 * time.Millisecond +) + +func (c *Consortium) delayForConsortiumV2Fork(snap *Snapshot, header *types.Header) time.Duration { + delay := time.Until(time.Unix(int64(header.Time), 0)) // nolint: gosimple + if c.chainConfig.IsConsortiumV2(header.Number) { + return delay + } + if header.Difficulty.Cmp(diffNoTurn) == 0 { + // It's not our turn explicitly to sign, delay it a bit + wiggle := time.Duration(len(snap.Validators)/2+1) * wiggleTimeBeforeFork + delay += fixedBackOffTimeBeforeFork + time.Duration(rand.Int63n(int64(wiggle))) + } + return delay +} + func (c *Consortium) blockTimeForConsortiumV2Fork(snap *Snapshot, header, parent *types.Header) uint64 { blockTime := parent.Time + c.config.Period //if c.chainConfig.IsConsortiumV2(header.Number) { From 538cd07804392921a179b21d2fab67ce2edf51b8 Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Tue, 23 Aug 2022 15:21:48 +0700 Subject: [PATCH 18/52] [RON-202] feat: implement CalcDifficulty and Delay methods (#112) * feat: implement Seal method * feat: implement CalcDifficulty and Delay methods * chore: add switch condition for Delay and Author --- consensus/consortium/main.go | 10 +++++++++- consensus/consortium/v2/consortium.go | 19 +++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/consensus/consortium/main.go b/consensus/consortium/main.go index 5b8af8130f..29388faa01 100644 --- a/consensus/consortium/main.go +++ b/consensus/consortium/main.go @@ -39,6 +39,10 @@ func New(chainConfig *params.ChainConfig, db ethdb.Database, ee *ethapi.PublicBl // Author since v1 and v2 are implemented the same logic, so we don't need to check whether the current block is version 1 // or version 2 func (c *Consortium) Author(header *types.Header) (common.Address, error) { + if c.chainConfig.IsConsortiumV2(header.Number) { + return c.v2.Author(header) + } + return c.v1.Author(header) } @@ -109,7 +113,11 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head } func (c *Consortium) Delay(chain consensus.ChainReader, header *types.Header) *time.Duration { - return nil + if c.chainConfig.IsConsortiumV2(header.Number) { + return c.v2.Delay(chain, header) + } + + return c.v1.Delay(chain, header) } func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index cd16b28989..b328d7348f 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -684,7 +684,18 @@ func (c *Consortium) Authorize(signer common.Address, signFn consortiumCommon.Si } func (c *Consortium) Delay(chain consensus.ChainReader, header *types.Header) *time.Duration { - return nil + number := header.Number.Uint64() + snap, err := c.snapshot(chain, number-1, header.ParentHash, nil) + if err != nil { + return nil + } + delay := c.delayForConsortiumV2Fork(snap, header) + // The blocking time should be no more than half of period + half := time.Duration(c.config.Period) * time.Second / 2 + if delay > half { + delay = half + } + return &delay } func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { @@ -780,7 +791,11 @@ func (c *Consortium) APIs(chain consensus.ChainHeaderReader) []rpc.API { } func (c *Consortium) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { - return nil + snap, err := c.snapshot(chain, parent.Number.Uint64(), parent.Hash(), nil) + if err != nil { + return nil + } + return CalcDifficulty(snap, c.val) } // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty From d629b9afda855493ff59060c7a6af2bd085fbd45 Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Tue, 23 Aug 2022 17:14:42 +0700 Subject: [PATCH 19/52] Chore: Add sign tx fn to contract integrator (#110) * chore: Add signFnTx to contract integrator, add deploy validators to generated validators * fix: change FinanlizeAssemble that returns receipts to apply changing receipts length during processing system contracts * fix: change gas limit * fix: Add check recent to v1/verifySeal * chore: Add contract_test which contains deploy and addNode codes * fix: applying v2 contract from v1 --- consensus/clique/clique.go | 4 +- consensus/consensus.go | 2 +- consensus/consortium/common/contract.go | 77 +++++----- consensus/consortium/common/contract_test.go | 133 ++++++++++++++++++ consensus/consortium/main.go | 2 +- consensus/consortium/v1/consortium.go | 87 ++++++++++-- consensus/consortium/v2/consortium.go | 35 +++-- consensus/ethash/consensus.go | 4 +- core/chain_makers.go | 4 +- core/state_processor.go | 6 + .../generated_contracts/validators/main.go | 24 +++- eth/catalyst/api.go | 2 +- miner/worker.go | 6 +- params/config.go | 8 +- 14 files changed, 313 insertions(+), 81 deletions(-) create mode 100644 consensus/consortium/common/contract_test.go diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index fc690e3b42..852fe417cd 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -574,12 +574,12 @@ func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Heade // FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set, // nor block rewards given, and returns the final block. func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, - uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { + uncles []*types.Header, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) { // Finalize block c.Finalize(chain, header, state, &txs, uncles, nil, nil, nil) // Assemble and return the final block for sealing - return types.NewBlock(header, txs, nil, receipts, trie.NewStackTrie(nil)), nil + return types.NewBlock(header, txs, nil, receipts, trie.NewStackTrie(nil)), receipts, nil } // Authorize injects a private key into the consensus engine to mint new blocks diff --git a/consensus/consensus.go b/consensus/consensus.go index 88f782781e..76bf0b517b 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -107,7 +107,7 @@ type Engine interface { // Note: The block header and state database might be updated to reflect any // consensus rules that happen at finalization (e.g. block rewards). FinalizeAndAssemble(chain ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, - uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) + uncles []*types.Header, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) // Seal generates a new sealing request for the given input block and pushes // the result into the given channel. diff --git a/consensus/consortium/common/contract.go b/consensus/consortium/common/contract.go index 1878bd4ff6..3b05f59b2c 100644 --- a/consensus/consortium/common/contract.go +++ b/consensus/consortium/common/contract.go @@ -27,45 +27,54 @@ import ( var errMethodUnimplemented = errors.New("method is unimplemented") +func getTransactionOpts(from common.Address, nonce uint64, chainId *big.Int, signTxFn SignerTxFn) *bind.TransactOpts { + return &bind.TransactOpts{ + From: from, + GasLimit: 1000000, + GasPrice: big.NewInt(0), + Value: new(big.Int).SetUint64(0), + Nonce: new(big.Int).SetUint64(nonce), + NoSend: true, + Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) { + return signTxFn(accounts.Account{Address: from}, tx, chainId) + }, + } +} + type ContractIntegrator struct { + chainId *big.Int signer types.Signer validatorSC *validators.Validators + signTxFn SignerTxFn } -func NewContractIntegrator(config *chainParams.ChainConfig, backend bind.ContractBackend) (*ContractIntegrator, error) { +func NewContractIntegrator(config *chainParams.ChainConfig, backend bind.ContractBackend, signTxFn SignerTxFn) (*ContractIntegrator, error) { validatorSC, err := validators.NewValidators(config.ConsortiumV2Contracts.ValidatorSC, backend) if err != nil { return nil, err } return &ContractIntegrator{ + chainId: config.ChainID, validatorSC: validatorSC, + signTxFn: signTxFn, + signer: types.LatestSignerForChainID(config.ChainID), }, nil } func (c *ContractIntegrator) GetValidators(header *types.Header) ([]common.Address, error) { - addresses, err := c.validatorSC.GetValidators(&bind.CallOpts{ - BlockNumber: new(big.Int).Sub(header.Number, common.Big1), - }) + addresses, err := c.validatorSC.GetValidators(nil) if err != nil { return nil, err } - return addresses, nil } -func (c *ContractIntegrator) UpdateValidators(header *types.Header, opts *ApplyTransactOpts) error { +func (c *ContractIntegrator) UpdateValidators(opts *ApplyTransactOpts) error { coinbase := opts.Header.Coinbase nonce := opts.State.GetNonce(coinbase) - tx, err := c.validatorSC.UpdateValidators(&bind.TransactOpts{ - From: coinbase, - GasLimit: math.MaxUint64 / 2, - GasPrice: big.NewInt(0), - Value: new(big.Int).SetUint64(0), - Nonce: new(big.Int).SetUint64(nonce), - NoSend: true, - }) + tx, err := c.validatorSC.UpdateValidators(getTransactionOpts(coinbase, nonce, c.chainId, c.signTxFn)) if err != nil { return err } @@ -75,7 +84,7 @@ func (c *ContractIntegrator) UpdateValidators(header *types.Header, opts *ApplyT return err } - err = applyTransaction(msg, opts) + err = ApplyTransaction(msg, opts) if err != nil { return err } @@ -94,14 +103,7 @@ func (c *ContractIntegrator) DistributeRewards(to common.Address, opts *ApplyTra log.Trace("distribute to validator contract", "block hash", opts.Header.Hash(), "amount", balance) nonce := opts.State.GetNonce(coinbase) - tx, err := c.validatorSC.DepositReward(&bind.TransactOpts{ - From: coinbase, - GasLimit: math.MaxUint64 / 2, - GasPrice: big.NewInt(0), - Value: balance, - Nonce: new(big.Int).SetUint64(nonce), - NoSend: true, - }, to) + tx, err := c.validatorSC.DepositReward(getTransactionOpts(coinbase, nonce, c.chainId, c.signTxFn), to) if err != nil { return err } @@ -111,7 +113,7 @@ func (c *ContractIntegrator) DistributeRewards(to common.Address, opts *ApplyTra return err } - err = applyTransaction(msg, opts) + err = ApplyTransaction(msg, opts) if err != nil { return err } @@ -140,9 +142,10 @@ type ApplyTransactOpts struct { Signer types.Signer SignTxFn SignerTxFn EthAPI *ethapi.PublicBlockChainAPI + Coinbase common.Address } -func applyTransaction(msg types.Message, opts *ApplyTransactOpts) (err error) { +func ApplyTransaction(msg types.Message, opts *ApplyTransactOpts) (err error) { signer := opts.Signer signTxFn := opts.SignTxFn miner := opts.Header.Coinbase @@ -215,7 +218,7 @@ func applyMessage( opts *ApplyMessageOpts, ) (uint64, error) { // Create a new context to be used in the EVM environment - context := core.NewEVMBlockContext(opts.Header, opts.ChainContext, nil) + context := core.NewEVMBlockContext(opts.Header, opts.ChainContext, &opts.Header.Coinbase) // Create a new environment which holds all relevant information // about the transaction and calling mechanisms. vmenv := vm.NewEVM(context, vm.TxContext{Origin: msg.From(), GasPrice: big.NewInt(0)}, opts.State, opts.ChainConfig, vm.Config{}) @@ -234,7 +237,7 @@ func applyMessage( } type ConsortiumBackend struct { - ee *ethapi.PublicBlockChainAPI + *ethapi.PublicBlockChainAPI } func NewConsortiumBackend(ee *ethapi.PublicBlockChainAPI) *ConsortiumBackend { @@ -244,8 +247,12 @@ func NewConsortiumBackend(ee *ethapi.PublicBlockChainAPI) *ConsortiumBackend { } func (b *ConsortiumBackend) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) { - block := rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(blockNumber.Int64())) - result, err := b.ee.GetCode(ctx, contract, block) + blkNumber := rpc.LatestBlockNumber + if blockNumber != nil { + blkNumber = rpc.BlockNumber(blockNumber.Int64()) + } + block := rpc.BlockNumberOrHashWithNumber(blkNumber) + result, err := b.GetCode(ctx, contract, block) if err != nil { return nil, err } @@ -254,11 +261,15 @@ func (b *ConsortiumBackend) CodeAt(ctx context.Context, contract common.Address, } func (b *ConsortiumBackend) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { - block := rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(blockNumber.Int64())) + blkNumber := rpc.LatestBlockNumber + if blockNumber != nil { + blkNumber = rpc.BlockNumber(blockNumber.Int64()) + } + block := rpc.BlockNumberOrHashWithNumber(blkNumber) gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2)) data := (hexutil.Bytes)(call.Data) - result, err := b.ee.Call(ctx, ethapi.TransactionArgs{ + result, err := b.Call(ctx, ethapi.TransactionArgs{ Gas: &gas, To: call.To, Data: &data, @@ -267,11 +278,11 @@ func (b *ConsortiumBackend) CallContract(ctx context.Context, call ethereum.Call return nil, err } - return result.MarshalText() + return result, nil } func (b *ConsortiumBackend) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { - return b.ee.GetHeader(ctx, rpc.BlockNumber(number.Int64())) + return b.GetHeader(ctx, rpc.BlockNumber(number.Int64())) } func (b *ConsortiumBackend) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) { diff --git a/consensus/consortium/common/contract_test.go b/consensus/consortium/common/contract_test.go new file mode 100644 index 0000000000..4d4929751c --- /dev/null +++ b/consensus/consortium/common/contract_test.go @@ -0,0 +1,133 @@ +package common + +import ( + "context" + "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/systemcontracts/generated_contracts/validators" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/params" + "io/ioutil" + "math/big" + "testing" +) + +func loadKey() (*keystore.Key, error) { + keyjson, err := ioutil.ReadFile("/Users/mac/coding/ronin/PoS/local1/keystore/UTC--2022-08-21T07-22-03.047965000Z--da0479bed856764502249bec9a3acd1c3da2cf23") + if err != nil { + return nil, err + } + password := "123456" + return keystore.DecryptKey(keyjson, password) +} + +func TestDeployContract(t *testing.T) { + key, err := loadKey() + if err != nil { + t.Fatal(err) + } + + client, err := ethclient.Dial("http://localhost:8545") + if err != nil { + t.Fatal(err) + } + + address := common.HexToAddress("da0479bed856764502249bec9a3acd1c3da2cf23") + nonce, err := client.NonceAt(context.Background(), address, nil) + if err != nil { + t.Fatal(err) + } + + contractAddress, tx, _, err := validators.DeployValidators(&bind.TransactOpts{ + From: address, + Nonce: big.NewInt(int64(nonce)), + Signer: func(addr common.Address, tx *types.Transaction) (*types.Transaction, error) { + signer := types.LatestSignerForChainID(big.NewInt(2022)) + return types.SignTx(tx, signer, key.PrivateKey) + }, + Context: context.Background(), + }, client, "test") + + if err != nil { + t.Fatal(err) + } + println(tx.Hash().Hex()) + println(fmt.Sprintf("contractAddres:%s", contractAddress.Hex())) +} + +func TestAddNode(t *testing.T) { + client, err := ethclient.Dial("http://localhost:8545") + if err != nil { + t.Fatal(err) + } + contractIntegrator, err := NewContractIntegrator(¶ms.ChainConfig{ + ConsortiumV2Contracts: ¶ms.ConsortiumV2Contracts{ + ValidatorSC: common.HexToAddress("0x089f10d52008F962f9E09EFBD2E5275BFf56045b"), + }, + }, client, nil) + if err != nil { + t.Fatal(err) + } + key, err := loadKey() + if err != nil { + t.Fatal(err) + } + address := common.HexToAddress("da0479bed856764502249bec9a3acd1c3da2cf23") + nonce, err := client.NonceAt(context.Background(), address, nil) + if err != nil { + t.Fatal(err) + } + tx, err := contractIntegrator.validatorSC.AddNode(&bind.TransactOpts{ + From: address, + Nonce: big.NewInt(int64(nonce)), + Signer: func(addr common.Address, tx *types.Transaction) (*types.Transaction, error) { + signer := types.LatestSignerForChainID(big.NewInt(2022)) + return types.SignTx(tx, signer, key.PrivateKey) + }, + Context: context.Background(), + }, address, address) + if err != nil { + t.Fatal(err) + } + println(fmt.Sprintf("address:%s has been added, tx:%s", address.Hex(), tx.Hash().Hex())) + + address2 := common.HexToAddress("bd1baea7e8a4f6c156039adc536c5bbce68add59") + tx, err = contractIntegrator.validatorSC.AddNode(&bind.TransactOpts{ + From: address, + Nonce: big.NewInt(int64(nonce + 1)), + Signer: func(addr common.Address, tx *types.Transaction) (*types.Transaction, error) { + signer := types.LatestSignerForChainID(big.NewInt(2022)) + return types.SignTx(tx, signer, key.PrivateKey) + }, + Context: context.Background(), + }, address2, address2) + if err != nil { + t.Fatal(err) + } + println(fmt.Sprintf("address:%s has been added, tx:%s", address2.Hex(), tx.Hash().Hex())) +} + +func TestGetLatestValidators(t *testing.T) { + client, err := ethclient.Dial("http://localhost:8545") + if err != nil { + t.Fatal(err) + } + contractIntegrator, err := NewContractIntegrator(¶ms.ChainConfig{ + ConsortiumV2Contracts: ¶ms.ConsortiumV2Contracts{ + ValidatorSC: common.HexToAddress("089f10d52008F962f9E09EFBD2E5275BFf56045b"), + }, + }, client, nil) + if err != nil { + t.Fatal(err) + } + vals, err := contractIntegrator.validatorSC.GetValidators(nil) + if err != nil { + t.Fatal(err) + } + for _, val := range vals { + println(val.Hex()) + } +} diff --git a/consensus/consortium/main.go b/consensus/consortium/main.go index 29388faa01..b6318cda76 100644 --- a/consensus/consortium/main.go +++ b/consensus/consortium/main.go @@ -104,7 +104,7 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H } func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, - txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { + txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) { if c.chainConfig.IsConsortiumV2(header.Number) { return c.v2.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts) } diff --git a/consensus/consortium/v1/consortium.go b/consensus/consortium/v1/consortium.go index ac85260699..813301b84c 100644 --- a/consensus/consortium/v1/consortium.go +++ b/consensus/consortium/v1/consortium.go @@ -410,12 +410,22 @@ func (c *Consortium) verifySeal(chain consensus.ChainHeaderReader, header *types return errWrongCoinbase } - if _, ok := snap.SignerSet[signer]; !ok { - return errUnauthorizedSigner + validators, err := c.getValidatorsFromLastCheckpoint(chain, number-1, nil) + if err != nil { + return err + } + + // If we're amongst the recent signers, wait for the next block + for seen, recent := range snap.Recents { + if recent == signer { + // Signer is among recents, only wait if the current block doesn't shift it out + if limit := uint64(len(validators)/2 + 1); seen > number-limit { + return errors.New("signed recently, must wait for others") + } + } } // Ensure that the difficulty corresponds to the turn-ness of the signer - validators := snap.SignerList inturn := c.signerInTurn(signer, header.Number.Uint64(), validators) if inturn && header.Difficulty.Cmp(diffInTurn) != 0 { return consortiumCommon.ErrWrongDifficulty @@ -429,10 +439,6 @@ func (c *Consortium) verifySeal(chain consensus.ChainHeaderReader, header *types // Prepare implements consensus.Engine, preparing all the consensus fields of the // header for running the transactions on top. func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { - if err := c.initContract(); err != nil { - return err - } - // Set the Coinbase address as the signer header.Coinbase = c.val header.Nonce = types.BlockNonce{} @@ -486,6 +492,36 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H return err } + if len(*systemTxs) > 0 { + log.Info("processing system tx from consortium v1", "systemTxs", len(*systemTxs), "coinbase", header.Coinbase.Hex()) + msg, err := (*systemTxs)[0].AsMessage(c.signer, big.NewInt(0)) + if err != nil { + return err + } + transactOpts := &consortiumCommon.ApplyTransactOpts{ + ApplyMessageOpts: &consortiumCommon.ApplyMessageOpts{ + State: state, + Header: header, + ChainConfig: c.chainConfig, + ChainContext: consortiumCommon.ChainContext{Chain: chain, Consortium: c}, + }, + Txs: txs, + Receipts: receipts, + ReceivedTxs: systemTxs, + UsedGas: usedGas, + Mining: false, + Signer: c.signer, + SignTxFn: c.signTxFn, + EthAPI: c.ethAPI, + } + if err = consortiumCommon.ApplyTransaction(msg, transactOpts); err != nil { + return err + } + if len(*systemTxs) > 0 { + return errors.New("the length of systemTxs does not match") + } + } + // No block rewards in PoA, so the state remains as is and uncles are dropped header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) header.UncleHash = types.CalcUncleHash(nil) @@ -496,9 +532,9 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H // FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set, // nor block rewards given, and returns the final block. func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, - uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { + uncles []*types.Header, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) { if err := c.initContract(); err != nil { - return nil, err + return nil, nil, err } // No block rewards in PoA, so the state remains as is and uncles are dropped @@ -517,18 +553,39 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head Receipts: &receipts, ReceivedTxs: nil, UsedGas: &header.GasUsed, - Mining: false, + Mining: true, Signer: c.signer, SignTxFn: c.signTxFn, EthAPI: c.ethAPI, } - if err := c.contract.UpdateValidators(header, transactOpts); err != nil { - log.Error("Failed to update validators: ", err) + if err := c.contract.UpdateValidators(transactOpts); err != nil { + log.Error("Failed to update validators", "err", err) + } + // should not happen. Once happen, stop the node is better than broadcast the block + if header.GasLimit < header.GasUsed { + return nil, nil, errors.New("gas consumption of system txs exceed the gas limit") } + header.UncleHash = types.CalcUncleHash(nil) + var blk *types.Block + var rootHash common.Hash + wg := sync.WaitGroup{} + wg.Add(2) + go func() { + rootHash = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) + wg.Done() + }() + go func() { + blk = types.NewBlock(header, txs, nil, receipts, trie.NewStackTrie(nil)) + wg.Done() + }() + wg.Wait() + blk.SetRoot(rootHash) + // Assemble and return the final block for sealing + return blk, receipts, nil } // Assemble and return the final block for sealing - return types.NewBlock(header, txs, nil, receipts, new(trie.Trie)), nil + return types.NewBlock(header, txs, nil, receipts, new(trie.Trie)), receipts, nil } // Authorize injects a private key into the consensus engine to mint new blocks @@ -580,7 +637,7 @@ func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, for seen, recent := range snap.Recents { if recent == signer { // Signer is among recents, only wait if the current block doesn't shift it out - if limit := uint64(len(validators)/2 + 1); number < limit || seen > number-limit { + if limit := uint64(len(validators)/2 + 1); seen > number-limit { return errors.New("signed recently, must wait for others") } } @@ -717,7 +774,7 @@ func (c *Consortium) signerInTurn(signer common.Address, number uint64, validato func (c *Consortium) initContract() error { if c.chainConfig.ConsortiumV2Block != nil && c.chainConfig.ConsortiumV2Contracts != nil { - contract, err := consortiumCommon.NewContractIntegrator(c.chainConfig, consortiumCommon.NewConsortiumBackend(c.ethAPI)) + contract, err := consortiumCommon.NewContractIntegrator(c.chainConfig, consortiumCommon.NewConsortiumBackend(c.ethAPI), c.signTxFn) if err != nil { return err } diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index b328d7348f..a299c24686 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -314,7 +314,7 @@ func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64, } // If an on-disk checkpoint snapshot can be found, use that - if number%checkpointInterval == 0 { + if number%c.config.Epoch == 0 { if s, err := loadSnapshot(c.config, c.signatures, c.db, hash, c.ethAPI); err == nil { log.Trace("Loaded snapshot from disk", "number", number, "hash", hash) snap = s @@ -323,20 +323,17 @@ func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64, } // If we're at the genesis, snapshot the initial state. - if number == 0 { + if number == 0 || c.chainConfig.IsConsortiumV2(big.NewInt(0).SetUint64(number+1)) { checkpoint := chain.GetHeaderByNumber(number) if checkpoint != nil { // get checkpoint data hash := checkpoint.Hash() - validatorBytes := checkpoint.Extra[extraVanity : len(checkpoint.Extra)-extraSeal] - // get validators from headers - validators, err := ParseValidators(validatorBytes) + validators, err := c.contract.GetValidators(checkpoint) if err != nil { return nil, err } - // new snap shot snap = newSnapshot(c.config, c.signatures, number, hash, validators, c.ethAPI) if err := snap.store(c.db); err != nil { return nil, err @@ -383,7 +380,7 @@ func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64, c.recents.Add(snap.Hash, snap) // If we've generated a new checkpoint snapshot, save to disk - if snap.Number%checkpointInterval == 0 && len(headers) > 0 { + if snap.Number%c.config.Epoch == 0 && len(headers) > 0 { if err = snap.store(c.db); err != nil { return nil, err } @@ -475,7 +472,7 @@ func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.He } header.Extra = header.Extra[:extraVanity] - if number%c.config.Epoch == 0 { + if number%c.config.Epoch == 0 || c.chainConfig.IsOnConsortiumV2(big.NewInt(int64(number))) { newValidators, err := c.contract.GetValidators(header) if err != nil { return err @@ -574,8 +571,8 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H } if header.Number.Uint64()%c.config.Epoch == c.config.Epoch-1 { - if err := c.contract.UpdateValidators(header, transactOpts); err != nil { - log.Error("Failed to update validators: ", err) + if err := c.contract.UpdateValidators(transactOpts); err != nil { + log.Error("Failed to update validators", "err", err) } } @@ -590,9 +587,9 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H } func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, - txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { + txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) { if err := c.initContract(); err != nil { - return nil, err + return nil, nil, err } // No block rewards in PoA, so the state remains as is and uncles are dropped @@ -622,7 +619,7 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head number := header.Number.Uint64() snap, err := c.snapshot(chain, number-1, header.ParentHash, nil) if err != nil { - return nil, err + return nil, nil, err } spoiledVal := snap.supposeValidator() signedRecently := false @@ -642,18 +639,18 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head } if header.Number.Uint64()%c.config.Epoch == c.config.Epoch-1 { - if err := c.contract.UpdateValidators(header, transactOpts); err != nil { - log.Error("Failed to update validators: ", err) + if err := c.contract.UpdateValidators(transactOpts); err != nil { + log.Error("Failed to update validators", "err", err) } } err := c.contract.DistributeRewards(c.val, transactOpts) if err != nil { - return nil, err + return nil, nil, err } // should not happen. Once happen, stop the node is better than broadcast the block if header.GasLimit < header.GasUsed { - return nil, errors.New("gas consumption of system txs exceed the gas limit") + return nil, nil, errors.New("gas consumption of system txs exceed the gas limit") } header.UncleHash = types.CalcUncleHash(nil) var blk *types.Block @@ -671,7 +668,7 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head wg.Wait() blk.SetRoot(rootHash) // Assemble and return the final block for sealing - return blk, nil + return blk, receipts, nil } func (c *Consortium) Authorize(signer common.Address, signFn consortiumCommon.SignerFn, signTxFn consortiumCommon.SignerTxFn) { @@ -814,7 +811,7 @@ func (c *Consortium) getValidatorsFromHeader(header *types.Header) []common.Addr } func (c *Consortium) initContract() error { - contract, err := consortiumCommon.NewContractIntegrator(c.chainConfig, consortiumCommon.NewConsortiumBackend(c.ethAPI)) + contract, err := consortiumCommon.NewContractIntegrator(c.chainConfig, consortiumCommon.NewConsortiumBackend(c.ethAPI), c.signTxFn) if err != nil { return err } diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index 89220d3685..f7a076572e 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -602,12 +602,12 @@ func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types. // FinalizeAndAssemble implements consensus.Engine, accumulating the block and // uncle rewards, setting the final state and assembling the block. func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, - txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { + txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) { // Finalize block ethash.Finalize(chain, header, state, &txs, uncles, nil, nil, nil) // Header seems complete, assemble into a block and return - return types.NewBlock(header, txs, uncles, receipts, trie.NewStackTrie(nil)), nil + return types.NewBlock(header, txs, uncles, receipts, trie.NewStackTrie(nil)), receipts, nil } func (ethash *Ethash) Delay(chain consensus.ChainReader, header *types.Header) *time.Duration { diff --git a/core/chain_makers.go b/core/chain_makers.go index 5db79506f8..f7105202e3 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -228,7 +228,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse } if b.engine != nil { // Finalize and seal the block - block, _ := b.engine.FinalizeAndAssemble(chainreader, b.header, statedb, b.txs, b.uncles, b.receipts) + block, receipts, _ := b.engine.FinalizeAndAssemble(chainreader, b.header, statedb, b.txs, b.uncles, b.receipts) // Write state changes to db root, err := statedb.Commit(config.IsEIP158(b.header.Number)) @@ -238,7 +238,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse if err := statedb.Database().TrieDB().Commit(root, false, nil); err != nil { panic(fmt.Sprintf("trie write error: %v", err)) } - return block, b.receipts + return block, receipts } return nil, nil } diff --git a/core/state_processor.go b/core/state_processor.go index e182f858ed..5fd8cd3fde 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -99,6 +99,12 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg } } + if p.config.ConsortiumV2Contracts != nil && p.config.IsOnConsortiumV2(big.NewInt(int64(block.NumberU64()+1))) && + p.config.ConsortiumV2Contracts.IsSystemContract(*tx.To()) { + systemTxs = append(systemTxs, tx) + continue + } + // set current transaction in block context to each transaction vmenv.Context.CurrentTransaction = tx // reset counter to start counting opcodes in new transaction diff --git a/core/systemcontracts/generated_contracts/validators/main.go b/core/systemcontracts/generated_contracts/validators/main.go index ca32c4099b..ce0bb5dbfd 100644 --- a/core/systemcontracts/generated_contracts/validators/main.go +++ b/core/systemcontracts/generated_contracts/validators/main.go @@ -30,13 +30,35 @@ var ( // ValidatorsMetaData contains all meta data concerning the Validators contract. var ValidatorsMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"consensusAddress\",\"type\":\"address\"},{\"internalType\":\"addresspayable\",\"name\":\"feeAddress\",\"type\":\"address\"}],\"name\":\"addNode\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"currentValidatorSet\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"consensusAddress\",\"type\":\"address\"},{\"internalType\":\"addresspayable\",\"name\":\"feeAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jailTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reward\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"currentValidatorSetMap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"valAddr\",\"type\":\"address\"}],\"name\":\"depositReward\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastUpdated\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getValidators\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateValidators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_version\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"consensusAddress\",\"type\":\"address\"},{\"internalType\":\"addresspayable\",\"name\":\"feeAddress\",\"type\":\"address\"}],\"name\":\"addNode\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"currentValidatorSet\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"consensusAddress\",\"type\":\"address\"},{\"internalType\":\"addresspayable\",\"name\":\"feeAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jailTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reward\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"currentValidatorSetMap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"valAddr\",\"type\":\"address\"}],\"name\":\"depositReward\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastUpdated\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getValidators\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateValidators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60806040526102586000806101000a81548161ffff021916908361ffff1602179055503480156200002f57600080fd5b5060405162000c3638038062000c3683398181016040528101906200005591906200019d565b80600190805190602001906200006d92919062000075565b505062000281565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282620000ad5760008555620000f9565b82601f10620000c857805160ff1916838001178555620000f9565b82800160010185558215620000f9579182015b82811115620000f8578251825591602001919060010190620000db565b5b5090506200010891906200010c565b5090565b5b80821115620001275760008160009055506001016200010d565b5090565b6000620001426200013c8462000216565b620001e2565b9050828152602081018484840111156200015b57600080fd5b6200016884828562000249565b509392505050565b600082601f8301126200018257600080fd5b8151620001948482602086016200012b565b91505092915050565b600060208284031215620001b057600080fd5b600082015167ffffffffffffffff811115620001cb57600080fd5b620001d98482850162000170565b91505092915050565b6000604051905081810181811067ffffffffffffffff821117156200020c576200020b6200027f565b5b8060405250919050565b600067ffffffffffffffff8211156200023457620002336200027f565b5b601f19601f8301169050602081019050919050565b60005b83811015620002695780820151818401526020810190506200024c565b8381111562000279576000848401525b50505050565bfe5b6109a580620002916000396000f3fe6080604052600436106100705760003560e01c806378121dd41161004e57806378121dd4146100e9578063ad3c9da614610114578063b7ab4db514610151578063db8ec38c1461017c57610070565b80632d497ba2146100755780636969a25c1461008c5780636ffa4dc1146100cd575b600080fd5b34801561008157600080fd5b5061008a6101a5565b005b34801561009857600080fd5b506100b360048036038101906100ae91906106c7565b610260565b6040516100c49594939291906107e2565b60405180910390f35b6100e760048036038101906100e29190610662565b6102e6565b005b3480156100f557600080fd5b506100fe610438565b60405161010b9190610877565b60405180910390f35b34801561012057600080fd5b5061013b60048036038101906101369190610662565b610442565b6040516101489190610877565b60405180910390f35b34801561015d57600080fd5b5061016661045a565b6040516101739190610835565b60405180910390f35b34801561018857600080fd5b506101a3600480360381019061019e919061068b565b610574565b005b4173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610213576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161020a90610857565b60405180910390fd5b6000439050600160008054906101000a900461ffff160361ffff1660008054906101000a900461ffff1661ffff16828161024957fe5b0614610255575061025e565b80600481905550505b565b6002818154811061027057600080fd5b90600052602060002090600502016000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060020154908060030154908060040154905085565b4173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610354576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161034b90610857565b60405180910390fd5b60005b6002805490508167ffffffffffffffff161015610433578173ffffffffffffffffffffffffffffffffffffffff1660028267ffffffffffffffff168154811061039c57fe5b906000526020600020906005020160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610426573460028267ffffffffffffffff168154811061040257fe5b90600052602060002090600502016004016000828254019250508190555050610435565b8080600101915050610357565b505b50565b6000600454905090565b60036020528060005260406000206000915090505481565b6060600060028054905067ffffffffffffffff8111801561047a57600080fd5b506040519080825280602002602001820160405280156104a95781602001602082028036833780820191505090505b50905060005b6002805490508167ffffffffffffffff16101561056c5760028167ffffffffffffffff16815481106104dd57fe5b906000526020600020906005020160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16828267ffffffffffffffff168151811061052557fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505080806001019150506104af565b508091505090565b600060026001816001815401808255809150500390600052602060002090600502019050828160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505050565b6000813590506106328161092a565b92915050565b60008135905061064781610941565b92915050565b60008135905061065c81610958565b92915050565b60006020828403121561067457600080fd5b600061068284828501610623565b91505092915050565b6000806040838503121561069e57600080fd5b60006106ac85828601610623565b92505060206106bd85828601610638565b9150509250929050565b6000602082840312156106d957600080fd5b60006106e78482850161064d565b91505092915050565b60006106fc8383610717565b60208301905092915050565b610711816108ee565b82525050565b610720816108dc565b82525050565b61072f816108dc565b82525050565b6000610740826108a2565b61074a81856108ba565b935061075583610892565b8060005b8381101561078657815161076d88826106f0565b9750610778836108ad565b925050600181019050610759565b5085935050505092915050565b60006107a06016836108cb565b91507f73656e646572206973206e6f7420636f696e62617365000000000000000000006000830152602082019050919050565b6107dc81610920565b82525050565b600060a0820190506107f76000830188610726565b6108046020830187610708565b61081160408301866107d3565b61081e60608301856107d3565b61082b60808301846107d3565b9695505050505050565b6000602082019050818103600083015261084f8184610735565b905092915050565b6000602082019050818103600083015261087081610793565b9050919050565b600060208201905061088c60008301846107d3565b92915050565b6000819050602082019050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b60006108e782610900565b9050919050565b60006108f982610900565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b610933816108dc565b811461093e57600080fd5b50565b61094a816108ee565b811461095557600080fd5b50565b61096181610920565b811461096c57600080fd5b5056fea264697066735822122015480192b8d148e024696a592a3fd5361e8c0abc4dc8ca3aebbc99c652f20abe64736f6c63430007060033", } // ValidatorsABI is the input ABI used to generate the binding from. // Deprecated: Use ValidatorsMetaData.ABI instead. var ValidatorsABI = ValidatorsMetaData.ABI +// ValidatorsBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use ValidatorsMetaData.Bin instead. +var ValidatorsBin = ValidatorsMetaData.Bin + +// DeployValidators deploys a new Ethereum contract, binding an instance of Validators to it. +func DeployValidators(auth *bind.TransactOpts, backend bind.ContractBackend, _version string) (common.Address, *types.Transaction, *Validators, error) { + parsed, err := ValidatorsMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(ValidatorsBin), backend, _version) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Validators{ValidatorsCaller: ValidatorsCaller{contract: contract}, ValidatorsTransactor: ValidatorsTransactor{contract: contract}, ValidatorsFilterer: ValidatorsFilterer{contract: contract}}, nil +} + // Validators is an auto generated Go binding around an Ethereum contract. type Validators struct { ValidatorsCaller // Read-only binding to the contract diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go index 38c7656535..df4103a858 100644 --- a/eth/catalyst/api.go +++ b/eth/catalyst/api.go @@ -206,7 +206,7 @@ func (api *consensusAPI) AssembleBlock(params assembleBlockParams) (*executableD } // Create the block. - block, err := api.eth.Engine().FinalizeAndAssemble(bc, header, env.state, transactions, nil /* uncles */, env.receipts) + block, _, err := api.eth.Engine().FinalizeAndAssemble(bc, header, env.state, transactions, nil /* uncles */, env.receipts) if err != nil { return nil, err } diff --git a/miner/worker.go b/miner/worker.go index 34c1500f42..298d1eccf5 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -938,7 +938,7 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) header.Coinbase = w.coinbase } if err := w.engine.Prepare(w.chain, header); err != nil { - log.Error("Failed to prepare header for mining", "err", err) + log.Error("Failed to prepare header for mining", "err", err, "number", header.Number.Uint64()) return } // If we are care about TheDAO hard-fork check whether to override the extra-data or not @@ -1036,9 +1036,8 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) // and commits new work if consensus engine is running. func (w *worker) commit(uncles []*types.Header, interval func(), update bool, start time.Time) error { // Deep copy receipts here to avoid interaction between different tasks. - receipts := copyReceipts(w.current.receipts) s := w.current.state.Copy() - block, err := w.engine.FinalizeAndAssemble(w.chain, w.current.header, s, w.current.txs, uncles, receipts) + block, receipts, err := w.engine.FinalizeAndAssemble(w.chain, w.current.header, s, w.current.txs, uncles, w.current.receipts) if err != nil { return err } @@ -1084,6 +1083,7 @@ func (w *worker) postSideBlock(event core.ChainSideEvent) { // totalFees computes total consumed miner fees in ETH. Block transactions and receipts have to have the same order. func totalFees(block *types.Block, receipts []*types.Receipt) *big.Float { + log.Info("getting totalFees", "block", block.Number().Int64()) feesWei := new(big.Int) for i, tx := range block.Transactions() { minerFee, _ := tx.EffectiveGasTip(block.BaseFee()) diff --git a/params/config.go b/params/config.go index 2a34c513d5..79d704de54 100644 --- a/params/config.go +++ b/params/config.go @@ -447,7 +447,11 @@ func (c *ChainConfig) String() string { default: engine = "unknown" } - return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Odysseus: %v, Fenix: %v, Muir Glacier: %v, Berlin: %v, London: %v, Arrow Glacier: %v, Engine: %v, Blacklist Contract: %v, Fenix Validator Contract: %v}", + validatorSC := common.HexToAddress("") + if c.ConsortiumV2Contracts != nil { + validatorSC = c.ConsortiumV2Contracts.ValidatorSC + } + return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Odysseus: %v, Fenix: %v, Muir Glacier: %v, Berlin: %v, London: %v, Arrow Glacier: %v, Engine: %v, Blacklist Contract: %v, Fenix Validator Contract: %v, ConsortiumV2: %v, ConsortiumV2.ValidatorSC: %v}", c.ChainID, c.HomesteadBlock, c.DAOForkBlock, @@ -468,6 +472,8 @@ func (c *ChainConfig) String() string { engine, c.BlacklistContractAddress, c.FenixValidatorContractAddress, + c.ConsortiumV2Block, + validatorSC.Hex(), ) } From f4ceaae846108cb03ab689ced2f0876bd809490f Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Thu, 25 Aug 2022 15:17:44 +0700 Subject: [PATCH 20/52] fix: Missing recents list in snapshot while switching v1 to v2 (#113) --- consensus/consortium/common/contract.go | 2 +- consensus/consortium/common/types.go | 6 +++++ consensus/consortium/main.go | 2 +- consensus/consortium/v1/consortium.go | 9 +++++++ consensus/consortium/v2/consortium.go | 31 +++++++++++++++++++++---- core/blockchain.go | 4 ---- eth/backend.go | 4 ++++ miner/worker.go | 5 +--- 8 files changed, 48 insertions(+), 15 deletions(-) diff --git a/consensus/consortium/common/contract.go b/consensus/consortium/common/contract.go index 3b05f59b2c..5fbe748967 100644 --- a/consensus/consortium/common/contract.go +++ b/consensus/consortium/common/contract.go @@ -101,7 +101,7 @@ func (c *ContractIntegrator) DistributeRewards(to common.Address, opts *ApplyTra opts.State.SetBalance(consensus.SystemAddress, big.NewInt(0)) opts.State.AddBalance(coinbase, balance) - log.Trace("distribute to validator contract", "block hash", opts.Header.Hash(), "amount", balance) + log.Info("distribute to validator contract", "block hash", opts.Header.Hash(), "amount", balance.String()) nonce := opts.State.GetNonce(coinbase) tx, err := c.validatorSC.DepositReward(getTransactionOpts(coinbase, nonce, c.chainId, c.signTxFn), to) if err != nil { diff --git a/consensus/consortium/common/types.go b/consensus/consortium/common/types.go index c707561b73..ede8ca5aef 100644 --- a/consensus/consortium/common/types.go +++ b/consensus/consortium/common/types.go @@ -2,6 +2,8 @@ package common import ( "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/core/types" "math/big" ) @@ -11,3 +13,7 @@ import ( type SignerFn func(accounts.Account, string, []byte) ([]byte, error) type SignerTxFn func(accounts.Account, *types.Transaction, *big.Int) (*types.Transaction, error) + +type ConsortiumAdapter interface { + GetRecents(chain consensus.ChainHeaderReader, number uint64) map[uint64]common.Address +} diff --git a/consensus/consortium/main.go b/consensus/consortium/main.go index b6318cda76..7897f04d5f 100644 --- a/consensus/consortium/main.go +++ b/consensus/consortium/main.go @@ -27,7 +27,7 @@ type Consortium struct { func New(chainConfig *params.ChainConfig, db ethdb.Database, ee *ethapi.PublicBlockChainAPI, genesisHash common.Hash) *Consortium { // Set any missing consensus parameters to their defaults consortiumV1 := v1.New(chainConfig, db, ee) - consortiumV2 := v2.New(chainConfig, db, ee, genesisHash) + consortiumV2 := v2.New(chainConfig, db, ee, genesisHash, consortiumV1) return &Consortium{ chainConfig: chainConfig, diff --git a/consensus/consortium/v1/consortium.go b/consensus/consortium/v1/consortium.go index 813301b84c..1da3f0dcbd 100644 --- a/consensus/consortium/v1/consortium.go +++ b/consensus/consortium/v1/consortium.go @@ -708,6 +708,15 @@ func (c *Consortium) CalcDifficulty(chain consensus.ChainHeaderReader, time uint return c.doCalcDifficulty(c.val, number, validators) } +func (c *Consortium) GetRecents(chain consensus.ChainHeaderReader, number uint64) map[uint64]common.Address { + header := chain.GetHeaderByNumber(number) + snap, err := c.snapshot(chain, number, header.Hash(), nil) + if err != nil { + return nil + } + return snap.Recents +} + func signerInList(signer common.Address, validators []common.Address) bool { for _, validator := range validators { if signer == validator { diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index a299c24686..6d7c160f9b 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -98,6 +98,7 @@ type Consortium struct { contract *consortiumCommon.ContractIntegrator fakeDiff bool + v1 consortiumCommon.ConsortiumAdapter } func New( @@ -105,6 +106,7 @@ func New( db ethdb.Database, ethAPI *ethapi.PublicBlockChainAPI, genesisHash common.Hash, + v1 consortiumCommon.ConsortiumAdapter, ) *Consortium { consortiumConfig := chainConfig.Consortium @@ -125,6 +127,7 @@ func New( recents: recents, signatures: signatures, signer: types.NewEIP155Signer(chainConfig.ChainID), + v1: v1, } } @@ -188,6 +191,10 @@ func (c *Consortium) VerifyHeaders(chain consensus.ChainHeaderReader, headers [] return abort, results } +func (c *Consortium) GetRecents(chain consensus.ChainHeaderReader, number uint64) map[uint64]common.Address { + return nil +} + func (c *Consortium) VerifyHeaderAndParents(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error { if header.Number == nil { return consortiumCommon.ErrUnknownBlock @@ -206,7 +213,7 @@ func (c *Consortium) VerifyHeaderAndParents(chain consensus.ChainHeaderReader, h return consortiumCommon.ErrMissingSignature } // check extra data - isEpoch := number%c.config.Epoch == 0 + isEpoch := number%c.config.Epoch == 0 || c.chainConfig.IsOnConsortiumV2(header.Number) // Ensure that the extra-data contains a signer list on checkpoint, but none otherwise signersBytes := len(header.Extra) - extraVanity - extraSeal @@ -300,6 +307,9 @@ func (c *Consortium) verifyCascadingFields(chain consensus.ChainHeaderReader, he } func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64, hash common.Hash, parents []*types.Header) (*Snapshot, error) { + if err := c.initContract(); err != nil { + return nil, err + } // Search for a snapshot in memory or on disk for checkpoints var ( headers []*types.Header @@ -323,7 +333,7 @@ func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64, } // If we're at the genesis, snapshot the initial state. - if number == 0 || c.chainConfig.IsConsortiumV2(big.NewInt(0).SetUint64(number+1)) { + if number == 0 || c.chainConfig.IsOnConsortiumV2(big.NewInt(0).SetUint64(number+1)) { checkpoint := chain.GetHeaderByNumber(number) if checkpoint != nil { // get checkpoint data @@ -335,6 +345,15 @@ func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64, } snap = newSnapshot(c.config, c.signatures, number, hash, validators, c.ethAPI) + // get recents from v1 if number is end of v1 + if c.chainConfig.IsOnConsortiumV2(big.NewInt(0).SetUint64(number + 1)) { + recents := c.v1.GetRecents(chain, number) + if recents != nil { + log.Info("adding previous recents to current snapshot", "number", number, "hash", hash.Hex(), "recents", recents) + snap.Recents = recents + } + } + // store snap to db if err := snap.store(c.db); err != nil { return nil, err } @@ -513,7 +532,7 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H if err != nil { return err } - + log.Info("[Finalize] Before applying system contract", "number", header.Number.Uint64(), "root", header.Root.Hex(), "stateRoot", state.IntermediateRoot(chain.Config().IsEIP158(header.Number)).Hex()) transactOpts := &consortiumCommon.ApplyTransactOpts{ ApplyMessageOpts: &consortiumCommon.ApplyMessageOpts{ State: state, @@ -580,6 +599,7 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H if err != nil { return err } + log.Info("[Finalize] After applying system contract", "root", header.Root.Hex(), "stateRoot", state.IntermediateRoot(chain.Config().IsEIP158(header.Number)).Hex()) if len(*systemTxs) > 0 { return errors.New("the length of systemTxs do not match") } @@ -662,13 +682,14 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head wg.Done() }() go func() { - blk = types.NewBlock(header, txs, nil, receipts, trie.NewStackTrie(nil)) + log.Info("[FinalizeAndAssemble] creating new block", "number", header.Number.Uint64(), "txs", len(*transactOpts.Txs), "receipts", len(*transactOpts.Receipts), "root", header.Root.Hex()) + blk = types.NewBlock(header, *transactOpts.Txs, nil, *transactOpts.Receipts, trie.NewStackTrie(nil)) wg.Done() }() wg.Wait() blk.SetRoot(rootHash) // Assemble and return the final block for sealing - return blk, receipts, nil + return blk, *transactOpts.Receipts, nil } func (c *Consortium) Authorize(signer common.Address, signFn consortiumCommon.SignerFn, signTxFn consortiumCommon.SignerTxFn) { diff --git a/core/blockchain.go b/core/blockchain.go index cb31fb7486..b807d34cd7 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -346,10 +346,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par } } } - // The first thing the node will do is reconstruct the verification data for - // the head block (ethash cache or clique voting snapshot). Might as well do - // it in advance. - bc.engine.VerifyHeader(bc, bc.CurrentHeader(), true) // Check the current state of the block hashes and make sure that we do not have any of the bad blocks in our chain for hash := range BadHashes { diff --git a/eth/backend.go b/eth/backend.go index 87642cecf8..e82bdee8ba 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -254,6 +254,10 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { return state.GetFenixValidators(stateDb, eth.blockchain.Config().FenixValidatorContractAddress), nil }) } + // The first thing the node will do is reconstruct the verification data for + // the head block (ethash cache or clique voting snapshot). Might as well do + // it in advance. + eth.engine.VerifyHeader(eth.blockchain, eth.blockchain.CurrentHeader(), true) eth.miner = miner.New(eth, &config.Miner, chainConfig, eth.EventMux(), eth.engine, eth.isLocalBlock) eth.miner.SetExtra(makeExtraData(config.Miner.ExtraData)) diff --git a/miner/worker.go b/miner/worker.go index 298d1eccf5..1dbb7dc28f 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -19,7 +19,6 @@ package miner import ( "bytes" "errors" - "github.com/ethereum/go-ethereum/core/systemcontracts" "math/big" "sync" "sync/atomic" @@ -686,6 +685,7 @@ func (w *worker) makeCurrent(parent *types.Block, header *types.Header) error { if err != nil { return err } + log.Info("[worker][makeCurrent] parent state", "parent", parent.Number().Uint64(), "stateRoot", state.IntermediateRoot(w.chainConfig.IsEIP158(header.Number)), "root", parent.Root().Hex()) state.StartPrefetcher("miner") env := &environment{ @@ -966,9 +966,6 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) misc.ApplyDAOHardFork(env.state) } - // Handle upgrade build-in system contract code - systemcontracts.UpgradeBuildInSystemContract(w.chainConfig, header.Number, env.state) - // Accumulate the uncles for the current block uncles := make([]*types.Header, 0, 2) commitUncles := func(blocks map[common.Hash]*types.Block) { From bb4573ce86217af32f203365091c679e42251eed Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Thu, 25 Aug 2022 17:13:33 +0700 Subject: [PATCH 21/52] fix: Implement `PoSA` interface methods to main Consortium (#114) * fix: Implement `PoSA` interface methods to main Consortium in order to get system contracts in v2 * chore: Remove unnecessary line --- consensus/consortium/common/contract.go | 48 +++++++++++++------- consensus/consortium/common/contract_test.go | 14 +++--- consensus/consortium/main.go | 20 ++++++++ consensus/consortium/v1/consortium.go | 2 +- consensus/consortium/v2/consortium.go | 2 +- 5 files changed, 60 insertions(+), 26 deletions(-) diff --git a/consensus/consortium/common/contract.go b/consensus/consortium/common/contract.go index 5fbe748967..be961af396 100644 --- a/consensus/consortium/common/contract.go +++ b/consensus/consortium/common/contract.go @@ -46,9 +46,10 @@ type ContractIntegrator struct { signer types.Signer validatorSC *validators.Validators signTxFn SignerTxFn + coinbase common.Address } -func NewContractIntegrator(config *chainParams.ChainConfig, backend bind.ContractBackend, signTxFn SignerTxFn) (*ContractIntegrator, error) { +func NewContractIntegrator(config *chainParams.ChainConfig, backend bind.ContractBackend, signTxFn SignerTxFn, coinbase common.Address) (*ContractIntegrator, error) { validatorSC, err := validators.NewValidators(config.ConsortiumV2Contracts.ValidatorSC, backend) if err != nil { return nil, err @@ -59,6 +60,7 @@ func NewContractIntegrator(config *chainParams.ChainConfig, backend bind.Contrac validatorSC: validatorSC, signTxFn: signTxFn, signer: types.LatestSignerForChainID(config.ChainID), + coinbase: coinbase, }, nil } @@ -71,19 +73,23 @@ func (c *ContractIntegrator) GetValidators(header *types.Header) ([]common.Addre } func (c *ContractIntegrator) UpdateValidators(opts *ApplyTransactOpts) error { - coinbase := opts.Header.Coinbase - nonce := opts.State.GetNonce(coinbase) - - tx, err := c.validatorSC.UpdateValidators(getTransactionOpts(coinbase, nonce, c.chainId, c.signTxFn)) - if err != nil { - return err - } - - msg, err := tx.AsMessage(c.signer, big.NewInt(0)) + nonce := opts.State.GetNonce(c.coinbase) + tx, err := c.validatorSC.UpdateValidators(getTransactionOpts(c.coinbase, nonce, c.chainId, c.signTxFn)) if err != nil { return err } - + msg := types.NewMessage( + opts.Header.Coinbase, tx.To(), + opts.Header.Nonce.Uint64(), + tx.Value(), + tx.Gas(), + big.NewInt(0), + big.NewInt(0), + big.NewInt(0), + tx.Data(), + tx.AccessList(), + false, + ) err = ApplyTransaction(msg, opts) if err != nil { return err @@ -102,16 +108,24 @@ func (c *ContractIntegrator) DistributeRewards(to common.Address, opts *ApplyTra opts.State.AddBalance(coinbase, balance) log.Info("distribute to validator contract", "block hash", opts.Header.Hash(), "amount", balance.String()) - nonce := opts.State.GetNonce(coinbase) - tx, err := c.validatorSC.DepositReward(getTransactionOpts(coinbase, nonce, c.chainId, c.signTxFn), to) + nonce := opts.State.GetNonce(c.coinbase) + tx, err := c.validatorSC.DepositReward(getTransactionOpts(c.coinbase, nonce, c.chainId, c.signTxFn), to) if err != nil { return err } - msg, err := tx.AsMessage(c.signer, big.NewInt(0)) - if err != nil { - return err - } + msg := types.NewMessage( + opts.Header.Coinbase, tx.To(), + opts.Header.Nonce.Uint64(), + tx.Value(), + tx.Gas(), + big.NewInt(0), + big.NewInt(0), + big.NewInt(0), + tx.Data(), + tx.AccessList(), + false, + ) err = ApplyTransaction(msg, opts) if err != nil { diff --git a/consensus/consortium/common/contract_test.go b/consensus/consortium/common/contract_test.go index 4d4929751c..16e7b03010 100644 --- a/consensus/consortium/common/contract_test.go +++ b/consensus/consortium/common/contract_test.go @@ -63,19 +63,19 @@ func TestAddNode(t *testing.T) { if err != nil { t.Fatal(err) } + key, err := loadKey() + if err != nil { + t.Fatal(err) + } + address := common.HexToAddress("da0479bed856764502249bec9a3acd1c3da2cf23") contractIntegrator, err := NewContractIntegrator(¶ms.ChainConfig{ ConsortiumV2Contracts: ¶ms.ConsortiumV2Contracts{ ValidatorSC: common.HexToAddress("0x089f10d52008F962f9E09EFBD2E5275BFf56045b"), }, - }, client, nil) + }, client, nil, address) if err != nil { t.Fatal(err) } - key, err := loadKey() - if err != nil { - t.Fatal(err) - } - address := common.HexToAddress("da0479bed856764502249bec9a3acd1c3da2cf23") nonce, err := client.NonceAt(context.Background(), address, nil) if err != nil { t.Fatal(err) @@ -119,7 +119,7 @@ func TestGetLatestValidators(t *testing.T) { ConsortiumV2Contracts: ¶ms.ConsortiumV2Contracts{ ValidatorSC: common.HexToAddress("089f10d52008F962f9E09EFBD2E5275BFf56045b"), }, - }, client, nil) + }, client, nil, common.Address{}) if err != nil { t.Fatal(err) } diff --git a/consensus/consortium/main.go b/consensus/consortium/main.go index 7897f04d5f..08f25814cd 100644 --- a/consensus/consortium/main.go +++ b/consensus/consortium/main.go @@ -177,3 +177,23 @@ func (c *Consortium) SetGetSCValidatorsFn(fn func() ([]common.Address, error)) { func (c *Consortium) SetGetFenixValidators(fn func() ([]common.Address, error)) { c.v1.SetGetFenixValidators(fn) } + +func (c *Consortium) IsSystemTransaction(tx *types.Transaction, header *types.Header) (bool, error) { + return c.v2.IsSystemTransaction(tx, header) +} + +func (c *Consortium) IsSystemContract(to *common.Address) bool { + return c.v2.IsSystemContract(to) +} + +func (c *Consortium) EnoughDistance(chain consensus.ChainReader, header *types.Header) bool { + return c.v2.EnoughDistance(chain, header) +} + +func (c *Consortium) IsLocalBlock(header *types.Header) bool { + return c.v2.IsLocalBlock(header) +} + +func (c *Consortium) AllowLightProcess(chain consensus.ChainReader, currentHeader *types.Header) bool { + return c.v2.AllowLightProcess(chain, currentHeader) +} diff --git a/consensus/consortium/v1/consortium.go b/consensus/consortium/v1/consortium.go index 1da3f0dcbd..e826c240ed 100644 --- a/consensus/consortium/v1/consortium.go +++ b/consensus/consortium/v1/consortium.go @@ -783,7 +783,7 @@ func (c *Consortium) signerInTurn(signer common.Address, number uint64, validato func (c *Consortium) initContract() error { if c.chainConfig.ConsortiumV2Block != nil && c.chainConfig.ConsortiumV2Contracts != nil { - contract, err := consortiumCommon.NewContractIntegrator(c.chainConfig, consortiumCommon.NewConsortiumBackend(c.ethAPI), c.signTxFn) + contract, err := consortiumCommon.NewContractIntegrator(c.chainConfig, consortiumCommon.NewConsortiumBackend(c.ethAPI), c.signTxFn, c.val) if err != nil { return err } diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index 6d7c160f9b..6436d229e0 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -832,7 +832,7 @@ func (c *Consortium) getValidatorsFromHeader(header *types.Header) []common.Addr } func (c *Consortium) initContract() error { - contract, err := consortiumCommon.NewContractIntegrator(c.chainConfig, consortiumCommon.NewConsortiumBackend(c.ethAPI), c.signTxFn) + contract, err := consortiumCommon.NewContractIntegrator(c.chainConfig, consortiumCommon.NewConsortiumBackend(c.ethAPI), c.signTxFn, c.val) if err != nil { return err } From 77bfe5422cac17ebe2a45f6a65f5779df7f6aa4d Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Fri, 26 Aug 2022 09:26:59 +0700 Subject: [PATCH 22/52] nit: Remove redundant codes (#115) - Remove redundant logs - Remove systemcontracts package - Move generated_contracts to consortium package --- consensus/consortium/common/contract.go | 6 +- consensus/consortium/common/contract_test.go | 36 +++++- .../generated_contracts/validators/main.go | 0 consensus/consortium/v2/consortium.go | 5 +- core/chain_makers.go | 4 - core/state_processor.go | 3 - core/systemcontracts/const.go | 9 -- core/systemcontracts/upgrade.go | 105 ------------------ miner/worker.go | 1 - 9 files changed, 38 insertions(+), 131 deletions(-) rename {core/systemcontracts => consensus/consortium}/generated_contracts/validators/main.go (100%) delete mode 100644 core/systemcontracts/const.go delete mode 100644 core/systemcontracts/upgrade.go diff --git a/consensus/consortium/common/contract.go b/consensus/consortium/common/contract.go index be961af396..2c808804e8 100644 --- a/consensus/consortium/common/contract.go +++ b/consensus/consortium/common/contract.go @@ -13,9 +13,9 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/consortium/generated_contracts/validators" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/systemcontracts/generated_contracts/validators" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/internal/ethapi" @@ -47,6 +47,7 @@ type ContractIntegrator struct { validatorSC *validators.Validators signTxFn SignerTxFn coinbase common.Address + config *chainParams.ChainConfig } func NewContractIntegrator(config *chainParams.ChainConfig, backend bind.ContractBackend, signTxFn SignerTxFn, coinbase common.Address) (*ContractIntegrator, error) { @@ -117,7 +118,7 @@ func (c *ContractIntegrator) DistributeRewards(to common.Address, opts *ApplyTra msg := types.NewMessage( opts.Header.Coinbase, tx.To(), opts.Header.Nonce.Uint64(), - tx.Value(), + balance, tx.Gas(), big.NewInt(0), big.NewInt(0), @@ -156,7 +157,6 @@ type ApplyTransactOpts struct { Signer types.Signer SignTxFn SignerTxFn EthAPI *ethapi.PublicBlockChainAPI - Coinbase common.Address } func ApplyTransaction(msg types.Message, opts *ApplyTransactOpts) (err error) { diff --git a/consensus/consortium/common/contract_test.go b/consensus/consortium/common/contract_test.go index 16e7b03010..7aba582710 100644 --- a/consensus/consortium/common/contract_test.go +++ b/consensus/consortium/common/contract_test.go @@ -6,7 +6,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/systemcontracts/generated_contracts/validators" + "github.com/ethereum/go-ethereum/consensus/consortium/generated_contracts/validators" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/params" @@ -117,7 +117,7 @@ func TestGetLatestValidators(t *testing.T) { } contractIntegrator, err := NewContractIntegrator(¶ms.ChainConfig{ ConsortiumV2Contracts: ¶ms.ConsortiumV2Contracts{ - ValidatorSC: common.HexToAddress("089f10d52008F962f9E09EFBD2E5275BFf56045b"), + ValidatorSC: common.HexToAddress("0x332c60a0CCFDF96E78A71Bc924345585425FB25d"), }, }, client, nil, common.Address{}) if err != nil { @@ -131,3 +131,35 @@ func TestGetLatestValidators(t *testing.T) { println(val.Hex()) } } + +func TestTransfer(t *testing.T) { + client, err := ethclient.Dial("http://localhost:8545") + if err != nil { + t.Fatal(err) + } + key, err := loadKey() + if err != nil { + t.Fatal(err) + } + nonce, err := client.NonceAt(context.Background(), key.Address, nil) + if err != nil { + t.Fatal(err) + } + to := common.HexToAddress("0xBD1baEa7e8a4F6C156039Adc536C5BBcE68ADd59") + signer := types.LatestSignerForChainID(big.NewInt(2022)) + tx, err := types.SignNewTx(key.PrivateKey, signer, + &types.LegacyTx{ + Nonce: nonce, + GasPrice: big.NewInt(500), + Gas: 21000, + To: &to, + Value: big.NewInt(0).Mul(big.NewInt(1), big.NewInt(0).Exp(big.NewInt(10), big.NewInt(18), nil)), + }) + if err != nil { + t.Fatal(err) + } + if err = client.SendTransaction(context.Background(), tx); err != nil { + t.Fatal(err) + } + println(tx.Hash().Hex()) +} diff --git a/core/systemcontracts/generated_contracts/validators/main.go b/consensus/consortium/generated_contracts/validators/main.go similarity index 100% rename from core/systemcontracts/generated_contracts/validators/main.go rename to consensus/consortium/generated_contracts/validators/main.go diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index 6436d229e0..c44ea720de 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -532,7 +532,6 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H if err != nil { return err } - log.Info("[Finalize] Before applying system contract", "number", header.Number.Uint64(), "root", header.Root.Hex(), "stateRoot", state.IntermediateRoot(chain.Config().IsEIP158(header.Number)).Hex()) transactOpts := &consortiumCommon.ApplyTransactOpts{ ApplyMessageOpts: &consortiumCommon.ApplyMessageOpts{ State: state, @@ -595,11 +594,10 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H } } - err = c.contract.DistributeRewards(c.val, transactOpts) + err = c.contract.DistributeRewards(header.Coinbase, transactOpts) if err != nil { return err } - log.Info("[Finalize] After applying system contract", "root", header.Root.Hex(), "stateRoot", state.IntermediateRoot(chain.Config().IsEIP158(header.Number)).Hex()) if len(*systemTxs) > 0 { return errors.New("the length of systemTxs do not match") } @@ -682,7 +680,6 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head wg.Done() }() go func() { - log.Info("[FinalizeAndAssemble] creating new block", "number", header.Number.Uint64(), "txs", len(*transactOpts.Txs), "receipts", len(*transactOpts.Receipts), "root", header.Root.Hex()) blk = types.NewBlock(header, *transactOpts.Txs, nil, *transactOpts.Receipts, trie.NewStackTrie(nil)) wg.Done() }() diff --git a/core/chain_makers.go b/core/chain_makers.go index f7105202e3..4055782f00 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -18,7 +18,6 @@ package core import ( "fmt" - "github.com/ethereum/go-ethereum/core/systemcontracts" "math/big" "github.com/ethereum/go-ethereum/common" @@ -219,9 +218,6 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse misc.ApplyDAOHardFork(statedb) } - // check and apply system contracts before finalizing block - systemcontracts.UpgradeBuildInSystemContract(config, b.header.Number, statedb) - // Execute any user modifications to the block if gen != nil { gen(i, b) diff --git a/core/state_processor.go b/core/state_processor.go index 5fd8cd3fde..e853d7a624 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -18,7 +18,6 @@ package core import ( "fmt" - "github.com/ethereum/go-ethereum/core/systemcontracts" "math/big" "github.com/ethereum/go-ethereum/common" @@ -72,8 +71,6 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 { misc.ApplyDAOHardFork(statedb) } - // update system contracts before processing EVM - systemcontracts.UpgradeBuildInSystemContract(p.config, block.Number(), statedb) blockContext := NewEVMBlockContext(header, p.bc, nil, publishEvents...) vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg) diff --git a/core/systemcontracts/const.go b/core/systemcontracts/const.go deleted file mode 100644 index d877d5124f..0000000000 --- a/core/systemcontracts/const.go +++ /dev/null @@ -1,9 +0,0 @@ -package systemcontracts - -const ( - ValidatorContract = "0x0000000000000000000000000000000000001000" - SlashContract = "0x0000000000000000000000000000000000001001" - - ConsortiumV2ValidatorContractCode = "" - ConsortiumV2SlashContractCode = "" -) diff --git a/core/systemcontracts/upgrade.go b/core/systemcontracts/upgrade.go deleted file mode 100644 index 705aeb29d0..0000000000 --- a/core/systemcontracts/upgrade.go +++ /dev/null @@ -1,105 +0,0 @@ -package systemcontracts - -import ( - "encoding/hex" - "fmt" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "math/big" -) - -type UpgradeConfig struct { - BeforeUpgrade upgradeHook - AfterUpgrade upgradeHook - ContractAddr common.Address - CommitUrl string - Code string -} - -type Upgrade struct { - UpgradeName string - Configs []*UpgradeConfig -} - -type upgradeHook func(blockNumber *big.Int, contractAddr common.Address, statedb *state.StateDB) error - -const ( - mainnet = "mainnet" - testnet = "testnet" -) - -var ( - GenesisHash common.Hash - //upgrade config - consortiumV2 = make(map[string]*Upgrade) -) - -func init() { - consortiumV2[mainnet] = &Upgrade{ - UpgradeName: "consortium v2", - Configs: []*UpgradeConfig{ - { - ContractAddr: common.HexToAddress(ValidatorContract), - CommitUrl: "", - Code: ConsortiumV2ValidatorContractCode, - }, - { - ContractAddr: common.HexToAddress(SlashContract), - CommitUrl: "", - Code: ConsortiumV2SlashContractCode, - }, - }, - } - consortiumV2[testnet] = consortiumV2[mainnet] -} - -func UpgradeBuildInSystemContract(config *params.ChainConfig, blockNumber *big.Int, statedb *state.StateDB) { - if config == nil || blockNumber == nil || statedb == nil { - return - } - var network string - switch GenesisHash { - /* Add mainnet genesis hash */ - case params.RoninMainnetGenesisHash: - network = mainnet - default: - network = testnet - } - - if config.IsOnConsortiumV2(blockNumber) { - applySystemContractUpgrade(consortiumV2[network], blockNumber, statedb) - } - -} - -func applySystemContractUpgrade(upgrade *Upgrade, blockNumber *big.Int, statedb *state.StateDB) { - if upgrade == nil { - log.Info("Empty upgrade config", "height", blockNumber.String()) - return - } - - log.Info(fmt.Sprintf("Apply upgrade %s at height %d", upgrade.UpgradeName, blockNumber.Int64())) - for _, cfg := range upgrade.Configs { - log.Info(fmt.Sprintf("Upgrade contract %s to commit %s", cfg.ContractAddr.String(), cfg.CommitUrl)) - - if cfg.BeforeUpgrade != nil { - if err := cfg.BeforeUpgrade(blockNumber, cfg.ContractAddr, statedb); err != nil { - panic(fmt.Errorf("contract address: %s, execute beforeUpgrade error: %s", cfg.ContractAddr.String(), err.Error())) - } - } - - newContractCode, err := hex.DecodeString(cfg.Code) - if err != nil { - panic(fmt.Errorf("failed to decode new contract code: %s", err.Error())) - } - statedb.SetCode(cfg.ContractAddr, newContractCode) - - if cfg.AfterUpgrade != nil { - if err := cfg.AfterUpgrade(blockNumber, cfg.ContractAddr, statedb); err != nil { - panic(fmt.Errorf("contract address: %s, execute afterUpgrade error: %s", cfg.ContractAddr.String(), err.Error())) - } - } - } -} diff --git a/miner/worker.go b/miner/worker.go index 1dbb7dc28f..f74f4028ce 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -685,7 +685,6 @@ func (w *worker) makeCurrent(parent *types.Block, header *types.Header) error { if err != nil { return err } - log.Info("[worker][makeCurrent] parent state", "parent", parent.Number().Uint64(), "stateRoot", state.IntermediateRoot(w.chainConfig.IsEIP158(header.Number)), "root", parent.Root().Hex()) state.StartPrefetcher("miner") env := &environment{ From 791752dd38e34d4bad71a4284fcc72a02d6da76c Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Thu, 1 Sep 2022 11:13:23 +0700 Subject: [PATCH 23/52] fix(genesis): remove system contract (#117) --- core/genesis.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/core/genesis.go b/core/genesis.go index 009037a2d1..11cc039d38 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -22,7 +22,6 @@ import ( "encoding/json" "errors" "fmt" - "github.com/ethereum/go-ethereum/core/systemcontracts" "math/big" "strings" @@ -145,10 +144,10 @@ func (e *GenesisMismatchError) Error() string { // SetupGenesisBlock writes or updates the genesis block in db. // The block that will be used is: // -// genesis == nil genesis != nil -// +------------------------------------------ -// db has no genesis | main-net default | genesis -// db has genesis | from DB | genesis (if compatible) +// genesis == nil genesis != nil +// +------------------------------------------ +// db has no genesis | main-net default | genesis +// db has genesis | from DB | genesis (if compatible) // // The stored chain configuration will be updated if it is compatible (i.e. does not // specify a fork block below the local head block). In case of a conflict, the @@ -165,7 +164,6 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, override } // Just commit the new block if there is no stored genesis block. stored := rawdb.ReadCanonicalHash(db, 0) - systemcontracts.GenesisHash = stored if (stored == common.Hash{}) { if genesis == nil { log.Info("Writing default main-net genesis block") From 50b803525b07b598598fcfe183f0f9412dc4d67a Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Thu, 1 Sep 2022 11:27:37 +0700 Subject: [PATCH 24/52] feat: write unit tests for utils (#116) --- consensus/consortium/common/utils.go | 2 + consensus/consortium/common/utils_test.go | 49 +++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 consensus/consortium/common/utils_test.go diff --git a/consensus/consortium/common/utils.go b/consensus/consortium/common/utils.go index d7d5dec16a..5a4a37bf47 100644 --- a/consensus/consortium/common/utils.go +++ b/consensus/consortium/common/utils.go @@ -4,6 +4,8 @@ import ( "github.com/ethereum/go-ethereum/common" ) +// ExtractAddressFromBytes extracts validators' address from extra data in header +// and return a list addresses func ExtractAddressFromBytes(bytes []byte) []common.Address { if bytes != nil && len(bytes) < common.AddressLength { return []common.Address{} diff --git a/consensus/consortium/common/utils_test.go b/consensus/consortium/common/utils_test.go new file mode 100644 index 0000000000..d91658ab41 --- /dev/null +++ b/consensus/consortium/common/utils_test.go @@ -0,0 +1,49 @@ +package common + +import ( + "github.com/ethereum/go-ethereum/common" + "reflect" + "testing" +) + +func TestExtractAddressFromBytes(t *testing.T) { + sampleAddresses := []common.Address{ + common.HexToAddress("0x93b8eed0a1e082ae2f478fd7f8c14b1fc0261bb1"), + common.HexToAddress("0x93b8eed0a1e082ae2f478fd7f8c14b1fc0261bb1"), + common.HexToAddress("0x93b8eed0a1e082ae2f478fd7f8c14b1fc0261bb1"), + } + sampleBytes := make([]byte, 0, common.AddressLength*len(sampleAddresses)) + for _, address := range sampleAddresses { + sampleBytes = append(sampleBytes, address.Bytes()...) + } + + result := ExtractAddressFromBytes(sampleBytes) + + if !reflect.DeepEqual(result, sampleAddresses) { + t.Errorf("Output %q not equal to expected %q", result, sampleAddresses) + } +} + +func TestCompareSignersLists(t *testing.T) { + a := []common.Address{ + common.HexToAddress("0x93b8eed0a1e082ae2f478fd7f8c14b1fc0261bb1"), + common.HexToAddress("0x93b8eed0a1e082ae2f478fd7f8c14b1fc0261bb1"), + common.HexToAddress("0x93b8eed0a1e082ae2f478fd7f8c14b1fc0261bb1"), + } + b := []common.Address{ + common.HexToAddress("0x93b8eed0a1e082ae2f478fd7f8c14b1fc0261bb1"), + common.HexToAddress("0x93b8eed0a1e082ae2f478fd7f8c14b1fc0261bb1"), + common.HexToAddress("0x93b8eed0a1e082ae2f478fd7f8c14b1fc0261bb1"), + } + c := []common.Address{ + common.HexToAddress("0x93b8eed0a1e082ae2f478fd7f8c14b1fc0261bb1"), + } + + if CompareSignersLists(a, b) == false { + t.Errorf("Output %t not equal to expected %t", false, true) + } + + if CompareSignersLists(a, c) == true { + t.Errorf("Output %t not equal to expected %t", false, true) + } +} From 50ad7145a0124e597bb8130e65f090bb288f7e91 Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Mon, 5 Sep 2022 11:09:04 +0700 Subject: [PATCH 25/52] fix: reorgs and incorrect nonce in consortium-v2 (#118) * fix: reorgs and incorrect nonce in consortium-v2 * chore: Remove getValidatorsFromLastCheckpoint, use snapshot instead --- consensus/consortium/common/contract.go | 6 +- consensus/consortium/common/contract_test.go | 60 +++++++++++++++++++- consensus/consortium/common/utils.go | 9 +++ consensus/consortium/v1/consortium.go | 11 +--- consensus/consortium/v2/consortium.go | 30 ++++++---- core/blockchain.go | 3 +- miner/worker.go | 3 +- 7 files changed, 92 insertions(+), 30 deletions(-) diff --git a/consensus/consortium/common/contract.go b/consensus/consortium/common/contract.go index 2c808804e8..d70f8ca99e 100644 --- a/consensus/consortium/common/contract.go +++ b/consensus/consortium/common/contract.go @@ -81,7 +81,7 @@ func (c *ContractIntegrator) UpdateValidators(opts *ApplyTransactOpts) error { } msg := types.NewMessage( opts.Header.Coinbase, tx.To(), - opts.Header.Nonce.Uint64(), + opts.State.GetNonce(opts.Header.Coinbase), tx.Value(), tx.Gas(), big.NewInt(0), @@ -108,8 +108,8 @@ func (c *ContractIntegrator) DistributeRewards(to common.Address, opts *ApplyTra opts.State.SetBalance(consensus.SystemAddress, big.NewInt(0)) opts.State.AddBalance(coinbase, balance) - log.Info("distribute to validator contract", "block hash", opts.Header.Hash(), "amount", balance.String()) nonce := opts.State.GetNonce(c.coinbase) + log.Info("distribute to validator contract", "block hash", opts.Header.Hash(), "amount", balance.String(), "coinbase", c.coinbase.Hex(), "nonce", nonce) tx, err := c.validatorSC.DepositReward(getTransactionOpts(c.coinbase, nonce, c.chainId, c.signTxFn), to) if err != nil { return err @@ -117,7 +117,7 @@ func (c *ContractIntegrator) DistributeRewards(to common.Address, opts *ApplyTra msg := types.NewMessage( opts.Header.Coinbase, tx.To(), - opts.Header.Nonce.Uint64(), + opts.State.GetNonce(opts.Header.Coinbase), balance, tx.Gas(), big.NewInt(0), diff --git a/consensus/consortium/common/contract_test.go b/consensus/consortium/common/contract_test.go index 7aba582710..a7510d7258 100644 --- a/consensus/consortium/common/contract_test.go +++ b/consensus/consortium/common/contract_test.go @@ -15,6 +15,8 @@ import ( "testing" ) +const contractAddress = "0x089f10d52008F962f9E09EFBD2E5275BFf56045b" + func loadKey() (*keystore.Key, error) { keyjson, err := ioutil.ReadFile("/Users/mac/coding/ronin/PoS/local1/keystore/UTC--2022-08-21T07-22-03.047965000Z--da0479bed856764502249bec9a3acd1c3da2cf23") if err != nil { @@ -70,7 +72,7 @@ func TestAddNode(t *testing.T) { address := common.HexToAddress("da0479bed856764502249bec9a3acd1c3da2cf23") contractIntegrator, err := NewContractIntegrator(¶ms.ChainConfig{ ConsortiumV2Contracts: ¶ms.ConsortiumV2Contracts{ - ValidatorSC: common.HexToAddress("0x089f10d52008F962f9E09EFBD2E5275BFf56045b"), + ValidatorSC: common.HexToAddress(contractAddress), }, }, client, nil, address) if err != nil { @@ -110,6 +112,60 @@ func TestAddNode(t *testing.T) { println(fmt.Sprintf("address:%s has been added, tx:%s", address2.Hex(), tx.Hash().Hex())) } +func TestGetNonce(t *testing.T) { + client, err := ethclient.Dial("http://localhost:8545") + if err != nil { + t.Fatal(err) + } + key, err := loadKey() + if err != nil { + t.Fatal(err) + } + nonce, err := client.NonceAt(context.Background(), key.Address, nil) + if err != nil { + t.Fatal(err) + } + println(nonce) +} + +func TestAddMoreNode(t *testing.T) { + client, err := ethclient.Dial("http://localhost:8545") + if err != nil { + t.Fatal(err) + } + key, err := loadKey() + if err != nil { + t.Fatal(err) + } + address := common.HexToAddress("089c3107402ae0d06d5953347a4c82ac8ce66f6c") + contractIntegrator, err := NewContractIntegrator(¶ms.ChainConfig{ + ConsortiumV2Contracts: ¶ms.ConsortiumV2Contracts{ + ValidatorSC: common.HexToAddress(contractAddress), + }, + }, client, nil, address) + if err != nil { + t.Fatal(err) + } + nonce, err := client.NonceAt(context.Background(), key.Address, nil) + if err != nil { + t.Fatal(err) + } + tx, err := contractIntegrator.validatorSC.AddNode(&bind.TransactOpts{ + From: key.Address, + Nonce: big.NewInt(int64(nonce)), + Signer: func(addr common.Address, tx *types.Transaction) (*types.Transaction, error) { + signer := types.LatestSignerForChainID(big.NewInt(2022)) + return types.SignTx(tx, signer, key.PrivateKey) + }, + Context: context.Background(), + }, address, address) + if err != nil { + t.Fatal(err) + } + println(fmt.Sprintf("address:%s has been added, tx:%s", address.Hex(), tx.Hash().Hex())) + +} + func TestGetLatestValidators(t *testing.T) { client, err := ethclient.Dial("http://localhost:8545") if err != nil { @@ -117,7 +173,7 @@ func TestGetLatestValidators(t *testing.T) { } contractIntegrator, err := NewContractIntegrator(¶ms.ChainConfig{ ConsortiumV2Contracts: ¶ms.ConsortiumV2Contracts{ - ValidatorSC: common.HexToAddress("0x332c60a0CCFDF96E78A71Bc924345585425FB25d"), + ValidatorSC: common.HexToAddress(contractAddress), }, }, client, nil, common.Address{}) if err != nil { diff --git a/consensus/consortium/common/utils.go b/consensus/consortium/common/utils.go index 5a4a37bf47..003c1d488a 100644 --- a/consensus/consortium/common/utils.go +++ b/consensus/consortium/common/utils.go @@ -30,3 +30,12 @@ func CompareSignersLists(list1 []common.Address, list2 []common.Address) bool { } return true } + +func SignerInList(signer common.Address, validators []common.Address) bool { + for _, validator := range validators { + if signer == validator { + return true + } + } + return false +} diff --git a/consensus/consortium/v1/consortium.go b/consensus/consortium/v1/consortium.go index e826c240ed..a2236df574 100644 --- a/consensus/consortium/v1/consortium.go +++ b/consensus/consortium/v1/consortium.go @@ -626,7 +626,7 @@ func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, if err != nil { return err } - if !signerInList(c.val, validators) { + if !consortiumCommon.SignerInList(c.val, validators) { return errUnauthorizedSigner } snap, err := c.snapshot(chain, number-1, header.ParentHash, nil) @@ -717,15 +717,6 @@ func (c *Consortium) GetRecents(chain consensus.ChainHeaderReader, number uint64 return snap.Recents } -func signerInList(signer common.Address, validators []common.Address) bool { - for _, validator := range validators { - if signer == validator { - return true - } - } - return false -} - func (c *Consortium) doCalcDifficulty(signer common.Address, number uint64, validators []common.Address) *big.Int { if c.signerInTurn(signer, number, validators) { return new(big.Int).Set(diffInTurn) diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index c44ea720de..2d7839db0c 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -23,6 +23,7 @@ import ( "golang.org/x/crypto/sha3" "io" "math/big" + "math/rand" "sort" "sync" "time" @@ -38,6 +39,7 @@ const ( extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal validatorBytesLength = common.AddressLength + wiggleTime = 1000 * time.Millisecond // Random delay (per signer) to allow concurrent signers ) // Consortium proof-of-authority protocol constants. @@ -753,9 +755,16 @@ func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, } // Sweet, the protocol permits us to sign the block, wait for our time - delay := c.delayForConsortiumV2Fork(snap, header) + delay := time.Unix(int64(header.Time), 0).Sub(time.Now()) // nolint: gosimple + if !c.signerInTurn(val, number, snap.validators()) { + // It's not our turn explicitly to sign, delay it a bit + wiggle := time.Duration(len(snap.Validators)/2+1) * wiggleTime + delay += time.Duration(rand.Int63n(int64(wiggle))) + wiggleTime // delay for 0.5s more + + log.Trace("Out-of-turn signing requested", "wiggle", common.PrettyDuration(wiggle)) + } - log.Info("Sealing block with", "number", number, "delay", delay, "headerDifficulty", header.Difficulty, "val", val.Hex()) + log.Info("Sealing block with", "number", number, "delay", delay, "headerDifficulty", header.Difficulty, "val", val.Hex(), "txs", len(block.Transactions())) // Sign all the things! sig, err := signFn(accounts.Account{Address: val}, accounts.MimetypeConsortium, consortiumRLP(header, c.chainConfig.ChainID)) @@ -772,16 +781,6 @@ func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, return case <-time.After(delay): } - //if c.shouldWaitForCurrentBlockProcess(chain, header, snap) { - // log.Info("Waiting for received in turn block to process") - // select { - // case <-stop: - // log.Info("Received block process finished, abort block seal") - // return - // case <-time.After(time.Duration(processBackOffTime) * time.Second): - // log.Info("Process backoff time exhausted, start to seal block") - // } - //} select { case results <- block.WithSeal(header): @@ -838,6 +837,13 @@ func (c *Consortium) initContract() error { return nil } +// Check if it is the turn of the signer from the last checkpoint +func (c *Consortium) signerInTurn(signer common.Address, number uint64, validators []common.Address) bool { + lastCheckpoint := number / c.config.Epoch * c.config.Epoch + index := (number - lastCheckpoint) % uint64(len(validators)) + return validators[index] == signer +} + // ecrecover extracts the Ethereum account address from a signed header. func ecrecover(header *types.Header, sigcache *lru.ARCCache, chainId *big.Int) (common.Address, error) { // If the signature's already cached, return that diff --git a/core/blockchain.go b/core/blockchain.go index b807d34cd7..ba4ca5bf56 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -2176,13 +2176,14 @@ func (bc *BlockChain) reportBlock(block *types.Block, receipts types.Receipts, e ########## BAD BLOCK ######### Chain config: %v +Coinbase: %v Number: %v Hash: 0x%x %v Error: %v ############################## -`, bc.chainConfig, block.Number(), block.Hash(), receiptString, err)) +`, bc.chainConfig, block.Coinbase().Hex(), block.Number(), block.Hash(), receiptString, err)) } // InsertHeaderChain attempts to insert the given header chain in to the local diff --git a/miner/worker.go b/miner/worker.go index f74f4028ce..7900abb282 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -663,7 +663,7 @@ func (w *worker) resultLoop() { continue } log.Info("Successfully sealed new block", "number", block.Number(), "sealhash", sealhash, "hash", hash, - "elapsed", common.PrettyDuration(time.Since(task.createdAt))) + "elapsed", common.PrettyDuration(time.Since(task.createdAt)), "txs", len(block.Transactions())) // Broadcast the block and announce chain insertion event w.mux.Post(core.NewMinedBlockEvent{Block: block}) @@ -1079,7 +1079,6 @@ func (w *worker) postSideBlock(event core.ChainSideEvent) { // totalFees computes total consumed miner fees in ETH. Block transactions and receipts have to have the same order. func totalFees(block *types.Block, receipts []*types.Receipt) *big.Float { - log.Info("getting totalFees", "block", block.Number().Int64()) feesWei := new(big.Int) for i, tx := range block.Transactions() { minerFee, _ := tx.EffectiveGasTip(block.BaseFee()) From 0eeea9559e688739393cf658c749451d5caab04e Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Tue, 6 Sep 2022 14:19:46 +0700 Subject: [PATCH 26/52] chore: check signer in turn in `Seal` function instead of use `signerInTurn` function (#119) --- consensus/consortium/v2/consortium.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index 2d7839db0c..9a4302df76 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -756,7 +756,7 @@ func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, // Sweet, the protocol permits us to sign the block, wait for our time delay := time.Unix(int64(header.Time), 0).Sub(time.Now()) // nolint: gosimple - if !c.signerInTurn(val, number, snap.validators()) { + if header.Difficulty.Cmp(diffInTurn) != 0 { // It's not our turn explicitly to sign, delay it a bit wiggle := time.Duration(len(snap.Validators)/2+1) * wiggleTime delay += time.Duration(rand.Int63n(int64(wiggle))) + wiggleTime // delay for 0.5s more From 7df546e838933283e3edaae03a4cd477a70247cf Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Thu, 8 Sep 2022 15:37:30 +0700 Subject: [PATCH 27/52] feat: integrate smart contract (#120) * feat: integrate smart contract * chore: remove dposStaking config * chore: change generated contract from PascalCase to snake_case * chore: remove validators contract * chore: remove contract tests * chore: add comment to avoid misleading --- consensus/consortium/common/contract.go | 91 +- consensus/consortium/common/contract_test.go | 221 ---- .../ronin_validator_set.go | 958 ++++++++++++++++++ .../slash_indicator/slash_indicator.go | 731 +++++++++++++ .../generated_contracts/validators/main.go | 418 -------- consensus/consortium/v1/consortium.go | 2 +- consensus/consortium/v2/consortium.go | 17 +- params/config.go | 18 +- 8 files changed, 1775 insertions(+), 681 deletions(-) delete mode 100644 consensus/consortium/common/contract_test.go create mode 100644 consensus/consortium/generated_contracts/ronin_validator_set/ronin_validator_set.go create mode 100644 consensus/consortium/generated_contracts/slash_indicator/slash_indicator.go delete mode 100644 consensus/consortium/generated_contracts/validators/main.go diff --git a/consensus/consortium/common/contract.go b/consensus/consortium/common/contract.go index d70f8ca99e..a510f7a94b 100644 --- a/consensus/consortium/common/contract.go +++ b/consensus/consortium/common/contract.go @@ -13,7 +13,8 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/consortium/generated_contracts/validators" + "github.com/ethereum/go-ethereum/consensus/consortium/generated_contracts/ronin_validator_set" + "github.com/ethereum/go-ethereum/consensus/consortium/generated_contracts/slash_indicator" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -32,9 +33,10 @@ func getTransactionOpts(from common.Address, nonce uint64, chainId *big.Int, sig From: from, GasLimit: 1000000, GasPrice: big.NewInt(0), - Value: new(big.Int).SetUint64(0), - Nonce: new(big.Int).SetUint64(nonce), - NoSend: true, + // Set dummy value always equal 0 since it will be overridden when creating a new message + Value: new(big.Int).SetUint64(0), + Nonce: new(big.Int).SetUint64(nonce), + NoSend: true, Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) { return signTxFn(accounts.Account{Address: from}, tx, chainId) }, @@ -42,45 +44,52 @@ func getTransactionOpts(from common.Address, nonce uint64, chainId *big.Int, sig } type ContractIntegrator struct { - chainId *big.Int - signer types.Signer - validatorSC *validators.Validators - signTxFn SignerTxFn - coinbase common.Address - config *chainParams.ChainConfig + chainId *big.Int + signer types.Signer + roninValidatorSetSC *roninValidatorSet.RoninValidatorSet + slashIndicatorSC *slashIndicator.SlashIndicator + signTxFn SignerTxFn + coinbase common.Address + config *chainParams.ChainConfig } func NewContractIntegrator(config *chainParams.ChainConfig, backend bind.ContractBackend, signTxFn SignerTxFn, coinbase common.Address) (*ContractIntegrator, error) { - validatorSC, err := validators.NewValidators(config.ConsortiumV2Contracts.ValidatorSC, backend) + roninValidatorSetSC, err := roninValidatorSet.NewRoninValidatorSet(config.ConsortiumV2Contracts.RoninValidatorSet, backend) + if err != nil { + return nil, err + } + slashIndicatorSC, err := slashIndicator.NewSlashIndicator(config.ConsortiumV2Contracts.SlashIndicator, backend) if err != nil { return nil, err } return &ContractIntegrator{ - chainId: config.ChainID, - validatorSC: validatorSC, - signTxFn: signTxFn, - signer: types.LatestSignerForChainID(config.ChainID), - coinbase: coinbase, + chainId: config.ChainID, + roninValidatorSetSC: roninValidatorSetSC, + slashIndicatorSC: slashIndicatorSC, + signTxFn: signTxFn, + signer: types.LatestSignerForChainID(config.ChainID), + coinbase: coinbase, }, nil } func (c *ContractIntegrator) GetValidators(header *types.Header) ([]common.Address, error) { - addresses, err := c.validatorSC.GetValidators(nil) + addresses, err := c.roninValidatorSetSC.GetValidators(nil) if err != nil { return nil, err } return addresses, nil } -func (c *ContractIntegrator) UpdateValidators(opts *ApplyTransactOpts) error { +func (c *ContractIntegrator) WrapUpEpoch(opts *ApplyTransactOpts) error { nonce := opts.State.GetNonce(c.coinbase) - tx, err := c.validatorSC.UpdateValidators(getTransactionOpts(c.coinbase, nonce, c.chainId, c.signTxFn)) + tx, err := c.roninValidatorSetSC.WrapUpEpoch(getTransactionOpts(c.coinbase, nonce, c.chainId, c.signTxFn)) if err != nil { return err } msg := types.NewMessage( - opts.Header.Coinbase, tx.To(), + opts.Header.Coinbase, + tx.To(), opts.State.GetNonce(opts.Header.Coinbase), tx.Value(), tx.Gas(), @@ -99,7 +108,7 @@ func (c *ContractIntegrator) UpdateValidators(opts *ApplyTransactOpts) error { return err } -func (c *ContractIntegrator) DistributeRewards(to common.Address, opts *ApplyTransactOpts) error { +func (c *ContractIntegrator) SubmitBlockReward(opts *ApplyTransactOpts) error { coinbase := opts.Header.Coinbase balance := opts.State.GetBalance(consensus.SystemAddress) if balance.Cmp(common.Big0) <= 0 { @@ -109,15 +118,17 @@ func (c *ContractIntegrator) DistributeRewards(to common.Address, opts *ApplyTra opts.State.AddBalance(coinbase, balance) nonce := opts.State.GetNonce(c.coinbase) - log.Info("distribute to validator contract", "block hash", opts.Header.Hash(), "amount", balance.String(), "coinbase", c.coinbase.Hex(), "nonce", nonce) - tx, err := c.validatorSC.DepositReward(getTransactionOpts(c.coinbase, nonce, c.chainId, c.signTxFn), to) + log.Info("Submitted block reward", "block hash", opts.Header.Hash(), "amount", balance.String(), "coinbase", c.coinbase.Hex(), "nonce", nonce) + tx, err := c.roninValidatorSetSC.SubmitBlockReward(getTransactionOpts(c.coinbase, nonce, c.chainId, c.signTxFn)) if err != nil { return err } msg := types.NewMessage( - opts.Header.Coinbase, tx.To(), + opts.Header.Coinbase, + tx.To(), opts.State.GetNonce(opts.Header.Coinbase), + // Reassign value with the current balance. It will be overridden the current one. balance, tx.Gas(), big.NewInt(0), @@ -136,8 +147,34 @@ func (c *ContractIntegrator) DistributeRewards(to common.Address, opts *ApplyTra return nil } -func (c *ContractIntegrator) Slash(to common.Address, opts *ApplyTransactOpts) error { - return nil +func (c *ContractIntegrator) Slash(opts *ApplyTransactOpts, spoiledValidator common.Address) error { + log.Info("Slash validator", "block hash", opts.Header.Hash(), "address", spoiledValidator) + + nonce := opts.State.GetNonce(c.coinbase) + tx, err := c.slashIndicatorSC.Slash(getTransactionOpts(c.coinbase, nonce, c.chainId, c.signTxFn), spoiledValidator) + if err != nil { + return err + } + + msg := types.NewMessage( + opts.Header.Coinbase, + tx.To(), + opts.State.GetNonce(opts.Header.Coinbase), + tx.Value(), + tx.Gas(), + big.NewInt(0), + big.NewInt(0), + big.NewInt(0), + tx.Data(), + tx.AccessList(), + false, + ) + err = ApplyTransaction(msg, opts) + if err != nil { + return err + } + + return err } type ApplyMessageOpts struct { @@ -245,7 +282,7 @@ func applyMessage( msg.Value(), ) if err != nil { - log.Error("apply message failed", "msg", string(ret), "err", err) + log.Error("Apply message failed", "message", string(ret), "error", err) } return msg.Gas() - returnGas, err } diff --git a/consensus/consortium/common/contract_test.go b/consensus/consortium/common/contract_test.go deleted file mode 100644 index a7510d7258..0000000000 --- a/consensus/consortium/common/contract_test.go +++ /dev/null @@ -1,221 +0,0 @@ -package common - -import ( - "context" - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/consortium/generated_contracts/validators" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/params" - "io/ioutil" - "math/big" - "testing" -) - -const contractAddress = "0x089f10d52008F962f9E09EFBD2E5275BFf56045b" - -func loadKey() (*keystore.Key, error) { - keyjson, err := ioutil.ReadFile("/Users/mac/coding/ronin/PoS/local1/keystore/UTC--2022-08-21T07-22-03.047965000Z--da0479bed856764502249bec9a3acd1c3da2cf23") - if err != nil { - return nil, err - } - password := "123456" - return keystore.DecryptKey(keyjson, password) -} - -func TestDeployContract(t *testing.T) { - key, err := loadKey() - if err != nil { - t.Fatal(err) - } - - client, err := ethclient.Dial("http://localhost:8545") - if err != nil { - t.Fatal(err) - } - - address := common.HexToAddress("da0479bed856764502249bec9a3acd1c3da2cf23") - nonce, err := client.NonceAt(context.Background(), address, nil) - if err != nil { - t.Fatal(err) - } - - contractAddress, tx, _, err := validators.DeployValidators(&bind.TransactOpts{ - From: address, - Nonce: big.NewInt(int64(nonce)), - Signer: func(addr common.Address, tx *types.Transaction) (*types.Transaction, error) { - signer := types.LatestSignerForChainID(big.NewInt(2022)) - return types.SignTx(tx, signer, key.PrivateKey) - }, - Context: context.Background(), - }, client, "test") - - if err != nil { - t.Fatal(err) - } - println(tx.Hash().Hex()) - println(fmt.Sprintf("contractAddres:%s", contractAddress.Hex())) -} - -func TestAddNode(t *testing.T) { - client, err := ethclient.Dial("http://localhost:8545") - if err != nil { - t.Fatal(err) - } - key, err := loadKey() - if err != nil { - t.Fatal(err) - } - address := common.HexToAddress("da0479bed856764502249bec9a3acd1c3da2cf23") - contractIntegrator, err := NewContractIntegrator(¶ms.ChainConfig{ - ConsortiumV2Contracts: ¶ms.ConsortiumV2Contracts{ - ValidatorSC: common.HexToAddress(contractAddress), - }, - }, client, nil, address) - if err != nil { - t.Fatal(err) - } - nonce, err := client.NonceAt(context.Background(), address, nil) - if err != nil { - t.Fatal(err) - } - tx, err := contractIntegrator.validatorSC.AddNode(&bind.TransactOpts{ - From: address, - Nonce: big.NewInt(int64(nonce)), - Signer: func(addr common.Address, tx *types.Transaction) (*types.Transaction, error) { - signer := types.LatestSignerForChainID(big.NewInt(2022)) - return types.SignTx(tx, signer, key.PrivateKey) - }, - Context: context.Background(), - }, address, address) - if err != nil { - t.Fatal(err) - } - println(fmt.Sprintf("address:%s has been added, tx:%s", address.Hex(), tx.Hash().Hex())) - - address2 := common.HexToAddress("bd1baea7e8a4f6c156039adc536c5bbce68add59") - tx, err = contractIntegrator.validatorSC.AddNode(&bind.TransactOpts{ - From: address, - Nonce: big.NewInt(int64(nonce + 1)), - Signer: func(addr common.Address, tx *types.Transaction) (*types.Transaction, error) { - signer := types.LatestSignerForChainID(big.NewInt(2022)) - return types.SignTx(tx, signer, key.PrivateKey) - }, - Context: context.Background(), - }, address2, address2) - if err != nil { - t.Fatal(err) - } - println(fmt.Sprintf("address:%s has been added, tx:%s", address2.Hex(), tx.Hash().Hex())) -} - -func TestGetNonce(t *testing.T) { - client, err := ethclient.Dial("http://localhost:8545") - if err != nil { - t.Fatal(err) - } - key, err := loadKey() - if err != nil { - t.Fatal(err) - } - nonce, err := client.NonceAt(context.Background(), key.Address, nil) - if err != nil { - t.Fatal(err) - } - println(nonce) -} - -func TestAddMoreNode(t *testing.T) { - client, err := ethclient.Dial("http://localhost:8545") - if err != nil { - t.Fatal(err) - } - key, err := loadKey() - if err != nil { - t.Fatal(err) - } - address := common.HexToAddress("089c3107402ae0d06d5953347a4c82ac8ce66f6c") - contractIntegrator, err := NewContractIntegrator(¶ms.ChainConfig{ - ConsortiumV2Contracts: ¶ms.ConsortiumV2Contracts{ - ValidatorSC: common.HexToAddress(contractAddress), - }, - }, client, nil, address) - if err != nil { - t.Fatal(err) - } - nonce, err := client.NonceAt(context.Background(), key.Address, nil) - if err != nil { - t.Fatal(err) - } - tx, err := contractIntegrator.validatorSC.AddNode(&bind.TransactOpts{ - From: key.Address, - Nonce: big.NewInt(int64(nonce)), - Signer: func(addr common.Address, tx *types.Transaction) (*types.Transaction, error) { - signer := types.LatestSignerForChainID(big.NewInt(2022)) - return types.SignTx(tx, signer, key.PrivateKey) - }, - Context: context.Background(), - }, address, address) - if err != nil { - t.Fatal(err) - } - println(fmt.Sprintf("address:%s has been added, tx:%s", address.Hex(), tx.Hash().Hex())) - -} - -func TestGetLatestValidators(t *testing.T) { - client, err := ethclient.Dial("http://localhost:8545") - if err != nil { - t.Fatal(err) - } - contractIntegrator, err := NewContractIntegrator(¶ms.ChainConfig{ - ConsortiumV2Contracts: ¶ms.ConsortiumV2Contracts{ - ValidatorSC: common.HexToAddress(contractAddress), - }, - }, client, nil, common.Address{}) - if err != nil { - t.Fatal(err) - } - vals, err := contractIntegrator.validatorSC.GetValidators(nil) - if err != nil { - t.Fatal(err) - } - for _, val := range vals { - println(val.Hex()) - } -} - -func TestTransfer(t *testing.T) { - client, err := ethclient.Dial("http://localhost:8545") - if err != nil { - t.Fatal(err) - } - key, err := loadKey() - if err != nil { - t.Fatal(err) - } - nonce, err := client.NonceAt(context.Background(), key.Address, nil) - if err != nil { - t.Fatal(err) - } - to := common.HexToAddress("0xBD1baEa7e8a4F6C156039Adc536C5BBcE68ADd59") - signer := types.LatestSignerForChainID(big.NewInt(2022)) - tx, err := types.SignNewTx(key.PrivateKey, signer, - &types.LegacyTx{ - Nonce: nonce, - GasPrice: big.NewInt(500), - Gas: 21000, - To: &to, - Value: big.NewInt(0).Mul(big.NewInt(1), big.NewInt(0).Exp(big.NewInt(10), big.NewInt(18), nil)), - }) - if err != nil { - t.Fatal(err) - } - if err = client.SendTransaction(context.Background(), tx); err != nil { - t.Fatal(err) - } - println(tx.Hash().Hex()) -} diff --git a/consensus/consortium/generated_contracts/ronin_validator_set/ronin_validator_set.go b/consensus/consortium/generated_contracts/ronin_validator_set/ronin_validator_set.go new file mode 100644 index 0000000000..57f2c8f7ff --- /dev/null +++ b/consensus/consortium/generated_contracts/ronin_validator_set/ronin_validator_set.go @@ -0,0 +1,958 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package roninValidatorSet + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// RoninValidatorSetMetaData contains all meta data concerning the RoninValidatorSet contract. +var RoninValidatorSetMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"epochEndingAt\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"epochOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastUpdatedBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getValidators\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"_validatorList\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governanceAdminContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__governanceAdminContract\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__slashIndicatorContract\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__stakingContract\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"__maxValidatorNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"__numberOfBlocksInEpoch\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"__numberOfEpochsInPeriod\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_slashFelonyAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_slashDoubleSignAmount\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_addrList\",\"type\":\"address[]\"}],\"name\":\"jailed\",\"outputs\":[{\"internalType\":\"bool[]\",\"name\":\"_result\",\"type\":\"bool[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_addrList\",\"type\":\"address[]\"},{\"internalType\":\"uint256\",\"name\":\"_period\",\"type\":\"uint256\"}],\"name\":\"noPendingReward\",\"outputs\":[{\"internalType\":\"bool[]\",\"name\":\"_result\",\"type\":\"bool[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"numberOfBlocksInEpoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_numberOfBlocks\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"numberOfEpochsInPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_numberOfEpochs\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"periodEndingAt\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"periodOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validatorAddr\",\"type\":\"address\"}],\"name\":\"slashDoubleSign\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"slashDoubleSignAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validatorAddr\",\"type\":\"address\"}],\"name\":\"slashFelony\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"slashFelonyAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"slashIndicatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validatorAddr\",\"type\":\"address\"}],\"name\":\"slashMisdemeanor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakingContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"submitBlockReward\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"validatorCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"wrapUpEpoch\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + Bin: "0x60806040523480156200001157600080fd5b50620000226200002860201b60201c565b620001d3565b600060019054906101000a900460ff16156200007b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000729062000176565b60405180910390fd5b60ff801660008054906101000a900460ff1660ff161015620000ed5760ff6000806101000a81548160ff021916908360ff1602179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249860ff604051620000e49190620001b6565b60405180910390a15b565b600082825260208201905092915050565b7f496e697469616c697a61626c653a20636f6e747261637420697320696e69746960008201527f616c697a696e6700000000000000000000000000000000000000000000000000602082015250565b60006200015e602783620000ef565b91506200016b8262000100565b604082019050919050565b6000602082019050818103600083015262000191816200014f565b9050919050565b600060ff82169050919050565b620001b08162000198565b82525050565b6000602082019050620001cd6000830184620001a5565b92915050565b61321280620001e36000396000f3fe6080604052600436106101355760003560e01c806372e46810116100ab578063b7ab4db51161006f578063b7ab4db5146103fc578063df8fa43014610427578063dfe484cb14610450578063ea82f7841461047b578063ee99205c146104a6578063f8549af9146104d157610135565b806372e46810146103245780637593ff711461032e5780637ae46af31461036b57806387c891bd14610394578063a3d545f5146103bf57610135565b806352091f17116100fd57806352091f17146102335780635a08482d1461023d5780636aa1c2ef146102685780636d14c4e51461029357806371e594b3146102be578063722d298f146102fb57610135565b80630f43a6771461013a57806325a6b529146101655780633dc56e09146101a25780634454af9d146101cb5780635186dc7e14610208575b600080fd5b34801561014657600080fd5b5061014f61050e565b60405161015c91906121df565b60405180910390f35b34801561017157600080fd5b5061018c6004803603810190610187919061223a565b610514565b6040516101999190612282565b60405180910390f35b3480156101ae57600080fd5b506101c960048036038101906101c491906122fb565b61054b565b005b3480156101d757600080fd5b506101f260048036038101906101ed9190612481565b610766565b6040516101ff9190612588565b60405180910390f35b34801561021457600080fd5b5061021d6107d5565b60405161022a91906121df565b60405180910390f35b61023b6107df565b005b34801561024957600080fd5b50610252610b03565b60405161025f91906125b9565b60405180910390f35b34801561027457600080fd5b5061027d610b2d565b60405161028a91906121df565b60405180910390f35b34801561029f57600080fd5b506102a8610b37565b6040516102b591906121df565b60405180910390f35b3480156102ca57600080fd5b506102e560048036038101906102e091906125d4565b610b3d565b6040516102f29190612588565b60405180910390f35b34801561030757600080fd5b50610322600480360381019061031d91906122fb565b610c02565b005b61032c610dce565b005b34801561033a57600080fd5b506103556004803603810190610350919061223a565b61132b565b6040516103629190612282565b60405180910390f35b34801561037757600080fd5b50610392600480360381019061038d91906122fb565b611352565b005b3480156103a057600080fd5b506103a96114e3565b6040516103b691906121df565b60405180910390f35b3480156103cb57600080fd5b506103e660048036038101906103e1919061223a565b6114ed565b6040516103f391906121df565b60405180910390f35b34801561040857600080fd5b50610411611510565b60405161041e91906126ee565b60405180910390f35b34801561043357600080fd5b5061044e60048036038101906104499190612710565b611603565b005b34801561045c57600080fd5b50610465611827565b60405161047291906121df565b60405180910390f35b34801561048757600080fd5b5061049061182d565b60405161049d91906125b9565b60405180910390f35b3480156104b257600080fd5b506104bb611856565b6040516104c891906125b9565b60405180910390f35b3480156104dd57600080fd5b506104f860048036038101906104f3919061223a565b611880565b60405161050591906121df565b60405180910390f35b60035481565b60008060085460075461052791906127f5565b9050600181610536919061284f565b818461054291906128b2565b14915050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146105db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d29061298c565b60405180910390fd5b6001600a60006105ea43611880565b815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506000600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506000600d60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a5885f1d826040518263ffffffff1660e01b815260040161073191906125b9565b600060405180830381600087803b15801561074b57600080fd5b505af115801561075f573d6000803e3d6000fd5b5050505050565b606060005b82518110156107cf5761079783828151811061078a576107896129ac565b5b60200260200101516118b0565b8282815181106107aa576107a96129ac565b5b60200260200101901515908115158152505080806107c7906129db565b91505061076b565b50919050565b6000600854905090565b4173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461084d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161084490612a95565b60405180910390fd5b60003490506000339050610860816118fc565b61086b575050610b01565b610874816118b0565b806108e15750600a600061088743611880565b815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b156108ed575050610b01565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008173ffffffffffffffffffffffffffffffffffffffff16635a783656846040518263ffffffff1660e01b815260040161094f91906125b9565b602060405180830381865afa15801561096c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109909190612aca565b9050600061271085836109a391906127f5565b6109ad9190612af7565b9050600081866109bd919061284f565b905081600c60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610a0e9190612b28565b9250508190555080600d60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610a649190612b28565b92505081905550600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b863d71086836040518363ffffffff1660e01b8152600401610ac8929190612b5c565b600060405180830381600087803b158015610ae257600080fd5b505af1158015610af6573d6000803e3d6000fd5b505050505050505050505b565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600754905090565b600f5481565b606060005b8351811015610bfb57600a60008481526020019081526020016000206000858381518110610b7357610b726129ac565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16828281518110610bd657610bd56129ac565b5b6020026020010190151590811515815250508080610bf3906129db565b915050610b42565b5092915050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c92576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c899061298c565b60405180910390fd5b610c9b8161054b565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c905bb3582600e546040518363ffffffff1660e01b8152600401610cfa929190612b5c565b600060405180830381600087803b158015610d1457600080fd5b505af1158015610d28573d6000803e3d6000fd5b50505050600061e10043610d3c9190612b28565b9050610d87600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482611952565b600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505050565b4173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610e3c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e3390612a95565b60405180910390fd5b610e454361132b565b610e84576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7b90612bf7565b60405180910390fd5b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000806000610eb943611880565b90506000610ec643610514565b90506000610ed2611510565b905060005b815181101561119d57818181518110610ef357610ef26129ac565b5b60200260200101519550610f06866118b0565b80610f6b5750600a600085815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b61118a5782156110f7576000600c60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000600c60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555060008111156110f5578773ffffffffffffffffffffffffffffffffffffffff1663099feccb886040518263ffffffff1660e01b815260040161104091906125b9565b602060405180830381865afa15801561105d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110819190612c2c565b73ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050506110f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110eb90612ccb565b60405180910390fd5b5b505b600d60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054856111429190612b28565b94506000600d60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b8080611195906129db565b915050610ed7565b50811561123257600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ec35fe72826040518263ffffffff1660e01b81526004016111ff91906126ee565b600060405180830381600087803b15801561121957600080fd5b505af115801561122d573d6000803e3d6000fd5b505050505b8573ffffffffffffffffffffffffffffffffffffffff1663d45e6273826040518263ffffffff1660e01b815260040161126b91906126ee565b600060405180830381600087803b15801561128557600080fd5b505af1158015611299573d6000803e3d6000fd5b50505050600084111561131b578573ffffffffffffffffffffffffffffffffffffffff166108fc859081150290604051600060405180830381858888f1935050505061131a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161131190612ccb565b60405180910390fd5b5b61132361196c565b505050505050565b6000600160075461133c919061284f565b6007548361134a91906128b2565b149050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146113e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113d99061298c565b60405180910390fd5b6113eb8161054b565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c905bb3582600f546040518363ffffffff1660e01b815260040161144a929190612b5c565b600060405180830381600087803b15801561146457600080fd5b505af1158015611478573d6000803e3d6000fd5b505050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050565b6000600954905090565b60006001600754836114ff9190612af7565b6115099190612b28565b9050919050565b606060035467ffffffffffffffff81111561152e5761152d61233e565b5b60405190808252806020026020018201604052801561155c5781602001602082028036833780820191505090505b50905060005b81518110156115ff576004600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168282815181106115b2576115b16129ac565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505080806115f7906129db565b915050611562565b5090565b60008060019054906101000a900460ff161590508080156116345750600160008054906101000a900460ff1660ff16105b80611661575061164330611d86565b1580156116605750600160008054906101000a900460ff1660ff16145b5b6116a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161169790612d5d565b60405180910390fd5b60016000806101000a81548160ff021916908360ff16021790555080156116dd576001600060016101000a81548160ff0219169083151502179055505b88600060026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555085600681905550846007819055508360088190555082600e8190555081600f81905550801561181c5760008060016101000a81548160ff0219169083151502179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249860016040516118139190612dcf565b60405180910390a15b505050505050505050565b600e5481565b60008060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600160085460075461189491906127f5565b8361189f9190612af7565b6118a99190612b28565b9050919050565b6000600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020544311159050919050565b6000600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b6000818310156119625781611964565b825b905092915050565b600080600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ea11bf836040518163ffffffff1660e01b8152600401600060405180830381865afa1580156119dc573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611a059190612f44565b9150915060008251905060005b8351811015611b0757611a3e848281518110611a3157611a306129ac565b5b60200260200101516118b0565b15611af4578180611a4e90612fbc565b925050838281518110611a6457611a636129ac565b5b6020026020010151848281518110611a7f57611a7e6129ac565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050828281518110611acc57611acb6129ac565b5b6020026020010151838281518110611ae757611ae66129ac565b5b6020026020010181815250505b8080611aff906129db565b915050611a12565b50808352808252611b188383611da9565b92506000611b296006548551611fa7565b905060008190505b600354811015611c06576004600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600560006004600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81549060ff02191690558080611bfe906129db565b915050611b31565b5060005b81811015611d7157600560006004600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81549060ff02191690556000858281518110611ca957611ca86129ac565b5b602002602001015190506001600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550806004600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550508080611d69906129db565b915050611c0a565b50806003819055504360098190555050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60608251825114611def576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611de690613031565b60405180910390fd5b6000835103611e0057829050611fa1565b6000835167ffffffffffffffff811115611e1d57611e1c61233e565b5b604051908082528060200260200182016040528015611e5657816020015b611e436121ac565b815260200190600190039081611e3b5790505b50905060005b8151811015611ef5576040518060400160405280868381518110611e8357611e826129ac565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff168152602001858381518110611eb957611eb86129ac565b5b6020026020010151815250828281518110611ed757611ed66129ac565b5b60200260200101819052508080611eed906129db565b915050611e5c565b50611f0f81600060018451611f0a919061284f565b611fc0565b5060005b8151811015611f9b57818181518110611f2f57611f2e6129ac565b5b602002602001015160000151858281518110611f4e57611f4d6129ac565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080611f93906129db565b915050611f13565b50839150505b92915050565b6000818310611fb65781611fb8565b825b905092915050565b606060008390506000839050808203611fdd578592505050612178565b60008660028787611fee919061305b565b611ff8919061309e565b876120039190613108565b81518110612014576120136129ac565b5b602002602001015190505b818313612145575b806020015187848151811061203f5761203e6129ac565b5b602002602001015160200151111561206457828061205c9061314c565b935050612027565b5b868281518110612078576120776129ac565b5b602002602001015160200151816020015111156120a257818061209a90613194565b925050612065565b818313612140576120e78784815181106120bf576120be6129ac565b5b60200260200101518884815181106120da576120d96129ac565b5b602002602001015161217f565b8885815181106120fa576120f96129ac565b5b60200260200101898581518110612114576121136129ac565b5b602002602001018290528290525050828061212e9061314c565b935050818061213c90613194565b9250505b61201f565b8186121561215b57612158878784611fc0565b96505b848312156121715761216e878487611fc0565b96505b8693505050505b9392505050565b6121876121ac565b61218f6121ac565b600084905083818095508196505050848492509250509250929050565b604051806040016040528060008152602001600081525090565b6000819050919050565b6121d9816121c6565b82525050565b60006020820190506121f460008301846121d0565b92915050565b6000604051905090565b600080fd5b600080fd5b612217816121c6565b811461222257600080fd5b50565b6000813590506122348161220e565b92915050565b6000602082840312156122505761224f612204565b5b600061225e84828501612225565b91505092915050565b60008115159050919050565b61227c81612267565b82525050565b60006020820190506122976000830184612273565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006122c88261229d565b9050919050565b6122d8816122bd565b81146122e357600080fd5b50565b6000813590506122f5816122cf565b92915050565b60006020828403121561231157612310612204565b5b600061231f848285016122e6565b91505092915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6123768261232d565b810181811067ffffffffffffffff821117156123955761239461233e565b5b80604052505050565b60006123a86121fa565b90506123b4828261236d565b919050565b600067ffffffffffffffff8211156123d4576123d361233e565b5b602082029050602081019050919050565b600080fd5b60006123fd6123f8846123b9565b61239e565b905080838252602082019050602084028301858111156124205761241f6123e5565b5b835b81811015612449578061243588826122e6565b845260208401935050602081019050612422565b5050509392505050565b600082601f83011261246857612467612328565b5b81356124788482602086016123ea565b91505092915050565b60006020828403121561249757612496612204565b5b600082013567ffffffffffffffff8111156124b5576124b4612209565b5b6124c184828501612453565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6124ff81612267565b82525050565b600061251183836124f6565b60208301905092915050565b6000602082019050919050565b6000612535826124ca565b61253f81856124d5565b935061254a836124e6565b8060005b8381101561257b5781516125628882612505565b975061256d8361251d565b92505060018101905061254e565b5085935050505092915050565b600060208201905081810360008301526125a2818461252a565b905092915050565b6125b3816122bd565b82525050565b60006020820190506125ce60008301846125aa565b92915050565b600080604083850312156125eb576125ea612204565b5b600083013567ffffffffffffffff81111561260957612608612209565b5b61261585828601612453565b925050602061262685828601612225565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612665816122bd565b82525050565b6000612677838361265c565b60208301905092915050565b6000602082019050919050565b600061269b82612630565b6126a5818561263b565b93506126b08361264c565b8060005b838110156126e15781516126c8888261266b565b97506126d383612683565b9250506001810190506126b4565b5085935050505092915050565b600060208201905081810360008301526127088184612690565b905092915050565b600080600080600080600080610100898b03121561273157612730612204565b5b600061273f8b828c016122e6565b98505060206127508b828c016122e6565b97505060406127618b828c016122e6565b96505060606127728b828c01612225565b95505060806127838b828c01612225565b94505060a06127948b828c01612225565b93505060c06127a58b828c01612225565b92505060e06127b68b828c01612225565b9150509295985092959890939650565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000612800826121c6565b915061280b836121c6565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612844576128436127c6565b5b828202905092915050565b600061285a826121c6565b9150612865836121c6565b925082820390508181111561287d5761287c6127c6565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006128bd826121c6565b91506128c8836121c6565b9250826128d8576128d7612883565b5b828206905092915050565b600082825260208201905092915050565b7f526f6e696e56616c696461746f725365743a206d6574686f642063616c6c657260008201527f206d75737420626520736c61736820696e64696361746f7220636f6e7472616360208201527f7400000000000000000000000000000000000000000000000000000000000000604082015250565b60006129766041836128e3565b9150612981826128f4565b606082019050919050565b600060208201905081810360008301526129a581612969565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006129e6826121c6565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612a1857612a176127c6565b5b600182019050919050565b7f526f6e696e56616c696461746f725365743a206d6574686f642063616c6c657260008201527f206d75737420626520636f696e62617365000000000000000000000000000000602082015250565b6000612a7f6031836128e3565b9150612a8a82612a23565b604082019050919050565b60006020820190508181036000830152612aae81612a72565b9050919050565b600081519050612ac48161220e565b92915050565b600060208284031215612ae057612adf612204565b5b6000612aee84828501612ab5565b91505092915050565b6000612b02826121c6565b9150612b0d836121c6565b925082612b1d57612b1c612883565b5b828204905092915050565b6000612b33826121c6565b9150612b3e836121c6565b9250828201905080821115612b5657612b556127c6565b5b92915050565b6000604082019050612b7160008301856125aa565b612b7e60208301846121d0565b9392505050565b7f526f6e696e56616c696461746f725365743a206f6e6c7920616c6c6f7765642060008201527f61742074686520656e64206f662065706f636800000000000000000000000000602082015250565b6000612be16033836128e3565b9150612bec82612b85565b604082019050919050565b60006020820190508181036000830152612c1081612bd4565b9050919050565b600081519050612c26816122cf565b92915050565b600060208284031215612c4257612c41612204565b5b6000612c5084828501612c17565b91505092915050565b7f526f6e696e56616c696461746f725365743a20636f756c64206e6f742074726160008201527f6e7366657220524f4e0000000000000000000000000000000000000000000000602082015250565b6000612cb56029836128e3565b9150612cc082612c59565b604082019050919050565b60006020820190508181036000830152612ce481612ca8565b9050919050565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b6000612d47602e836128e3565b9150612d5282612ceb565b604082019050919050565b60006020820190508181036000830152612d7681612d3a565b9050919050565b6000819050919050565b600060ff82169050919050565b6000819050919050565b6000612db9612db4612daf84612d7d565b612d94565b612d87565b9050919050565b612dc981612d9e565b82525050565b6000602082019050612de46000830184612dc0565b92915050565b6000612dfd612df8846123b9565b61239e565b90508083825260208201905060208402830185811115612e2057612e1f6123e5565b5b835b81811015612e495780612e358882612c17565b845260208401935050602081019050612e22565b5050509392505050565b600082601f830112612e6857612e67612328565b5b8151612e78848260208601612dea565b91505092915050565b600067ffffffffffffffff821115612e9c57612e9b61233e565b5b602082029050602081019050919050565b6000612ec0612ebb84612e81565b61239e565b90508083825260208201905060208402830185811115612ee357612ee26123e5565b5b835b81811015612f0c5780612ef88882612ab5565b845260208401935050602081019050612ee5565b5050509392505050565b600082601f830112612f2b57612f2a612328565b5b8151612f3b848260208601612ead565b91505092915050565b60008060408385031215612f5b57612f5a612204565b5b600083015167ffffffffffffffff811115612f7957612f78612209565b5b612f8585828601612e53565b925050602083015167ffffffffffffffff811115612fa657612fa5612209565b5b612fb285828601612f16565b9150509250929050565b6000612fc7826121c6565b915060008203612fda57612fd96127c6565b5b600182039050919050565b7f536f7274696e673a20696e76616c6964206172726179206c656e677468000000600082015250565b600061301b601d836128e3565b915061302682612fe5565b602082019050919050565b6000602082019050818103600083015261304a8161300e565b9050919050565b6000819050919050565b600061306682613051565b915061307183613051565b9250828203905081811260008412168282136000851215161715613098576130976127c6565b5b92915050565b60006130a982613051565b91506130b483613051565b9250826130c4576130c3612883565b5b600160000383147f8000000000000000000000000000000000000000000000000000000000000000831416156130fd576130fc6127c6565b5b828205905092915050565b600061311382613051565b915061311e83613051565b925082820190508281121560008312168382126000841215161715613146576131456127c6565b5b92915050565b600061315782613051565b91507f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613189576131886127c6565b5b600182019050919050565b600061319f82613051565b91507f800000000000000000000000000000000000000000000000000000000000000082036131d1576131d06127c6565b5b60018203905091905056fea264697066735822122066a02006cc27f805b36f00068a836fd7319632c9c99ad555f71ee8a1b73f3fb464736f6c63430008100033", +} + +// RoninValidatorSetABI is the input ABI used to generate the binding from. +// Deprecated: Use RoninValidatorSetMetaData.ABI instead. +var RoninValidatorSetABI = RoninValidatorSetMetaData.ABI + +// RoninValidatorSetBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use RoninValidatorSetMetaData.Bin instead. +var RoninValidatorSetBin = RoninValidatorSetMetaData.Bin + +// DeployRoninValidatorSet deploys a new Ethereum contract, binding an instance of RoninValidatorSet to it. +func DeployRoninValidatorSet(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *RoninValidatorSet, error) { + parsed, err := RoninValidatorSetMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(RoninValidatorSetBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &RoninValidatorSet{RoninValidatorSetCaller: RoninValidatorSetCaller{contract: contract}, RoninValidatorSetTransactor: RoninValidatorSetTransactor{contract: contract}, RoninValidatorSetFilterer: RoninValidatorSetFilterer{contract: contract}}, nil +} + +// RoninValidatorSet is an auto generated Go binding around an Ethereum contract. +type RoninValidatorSet struct { + RoninValidatorSetCaller // Read-only binding to the contract + RoninValidatorSetTransactor // Write-only binding to the contract + RoninValidatorSetFilterer // Log filterer for contract events +} + +// RoninValidatorSetCaller is an auto generated read-only Go binding around an Ethereum contract. +type RoninValidatorSetCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// RoninValidatorSetTransactor is an auto generated write-only Go binding around an Ethereum contract. +type RoninValidatorSetTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// RoninValidatorSetFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type RoninValidatorSetFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// RoninValidatorSetSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type RoninValidatorSetSession struct { + Contract *RoninValidatorSet // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// RoninValidatorSetCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type RoninValidatorSetCallerSession struct { + Contract *RoninValidatorSetCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// RoninValidatorSetTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type RoninValidatorSetTransactorSession struct { + Contract *RoninValidatorSetTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// RoninValidatorSetRaw is an auto generated low-level Go binding around an Ethereum contract. +type RoninValidatorSetRaw struct { + Contract *RoninValidatorSet // Generic contract binding to access the raw methods on +} + +// RoninValidatorSetCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type RoninValidatorSetCallerRaw struct { + Contract *RoninValidatorSetCaller // Generic read-only contract binding to access the raw methods on +} + +// RoninValidatorSetTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type RoninValidatorSetTransactorRaw struct { + Contract *RoninValidatorSetTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewRoninValidatorSet creates a new instance of RoninValidatorSet, bound to a specific deployed contract. +func NewRoninValidatorSet(address common.Address, backend bind.ContractBackend) (*RoninValidatorSet, error) { + contract, err := bindRoninValidatorSet(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &RoninValidatorSet{RoninValidatorSetCaller: RoninValidatorSetCaller{contract: contract}, RoninValidatorSetTransactor: RoninValidatorSetTransactor{contract: contract}, RoninValidatorSetFilterer: RoninValidatorSetFilterer{contract: contract}}, nil +} + +// NewRoninValidatorSetCaller creates a new read-only instance of RoninValidatorSet, bound to a specific deployed contract. +func NewRoninValidatorSetCaller(address common.Address, caller bind.ContractCaller) (*RoninValidatorSetCaller, error) { + contract, err := bindRoninValidatorSet(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &RoninValidatorSetCaller{contract: contract}, nil +} + +// NewRoninValidatorSetTransactor creates a new write-only instance of RoninValidatorSet, bound to a specific deployed contract. +func NewRoninValidatorSetTransactor(address common.Address, transactor bind.ContractTransactor) (*RoninValidatorSetTransactor, error) { + contract, err := bindRoninValidatorSet(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &RoninValidatorSetTransactor{contract: contract}, nil +} + +// NewRoninValidatorSetFilterer creates a new log filterer instance of RoninValidatorSet, bound to a specific deployed contract. +func NewRoninValidatorSetFilterer(address common.Address, filterer bind.ContractFilterer) (*RoninValidatorSetFilterer, error) { + contract, err := bindRoninValidatorSet(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &RoninValidatorSetFilterer{contract: contract}, nil +} + +// bindRoninValidatorSet binds a generic wrapper to an already deployed contract. +func bindRoninValidatorSet(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(RoninValidatorSetABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_RoninValidatorSet *RoninValidatorSetRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _RoninValidatorSet.Contract.RoninValidatorSetCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_RoninValidatorSet *RoninValidatorSetRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.RoninValidatorSetTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_RoninValidatorSet *RoninValidatorSetRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.RoninValidatorSetTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_RoninValidatorSet *RoninValidatorSetCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _RoninValidatorSet.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_RoninValidatorSet *RoninValidatorSetTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_RoninValidatorSet *RoninValidatorSetTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.contract.Transact(opts, method, params...) +} + +// EpochEndingAt is a free data retrieval call binding the contract method 0x7593ff71. +// +// Solidity: function epochEndingAt(uint256 _block) view returns(bool) +func (_RoninValidatorSet *RoninValidatorSetCaller) EpochEndingAt(opts *bind.CallOpts, _block *big.Int) (bool, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "epochEndingAt", _block) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// EpochEndingAt is a free data retrieval call binding the contract method 0x7593ff71. +// +// Solidity: function epochEndingAt(uint256 _block) view returns(bool) +func (_RoninValidatorSet *RoninValidatorSetSession) EpochEndingAt(_block *big.Int) (bool, error) { + return _RoninValidatorSet.Contract.EpochEndingAt(&_RoninValidatorSet.CallOpts, _block) +} + +// EpochEndingAt is a free data retrieval call binding the contract method 0x7593ff71. +// +// Solidity: function epochEndingAt(uint256 _block) view returns(bool) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) EpochEndingAt(_block *big.Int) (bool, error) { + return _RoninValidatorSet.Contract.EpochEndingAt(&_RoninValidatorSet.CallOpts, _block) +} + +// EpochOf is a free data retrieval call binding the contract method 0xa3d545f5. +// +// Solidity: function epochOf(uint256 _block) view returns(uint256) +func (_RoninValidatorSet *RoninValidatorSetCaller) EpochOf(opts *bind.CallOpts, _block *big.Int) (*big.Int, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "epochOf", _block) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// EpochOf is a free data retrieval call binding the contract method 0xa3d545f5. +// +// Solidity: function epochOf(uint256 _block) view returns(uint256) +func (_RoninValidatorSet *RoninValidatorSetSession) EpochOf(_block *big.Int) (*big.Int, error) { + return _RoninValidatorSet.Contract.EpochOf(&_RoninValidatorSet.CallOpts, _block) +} + +// EpochOf is a free data retrieval call binding the contract method 0xa3d545f5. +// +// Solidity: function epochOf(uint256 _block) view returns(uint256) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) EpochOf(_block *big.Int) (*big.Int, error) { + return _RoninValidatorSet.Contract.EpochOf(&_RoninValidatorSet.CallOpts, _block) +} + +// GetLastUpdatedBlock is a free data retrieval call binding the contract method 0x87c891bd. +// +// Solidity: function getLastUpdatedBlock() view returns(uint256) +func (_RoninValidatorSet *RoninValidatorSetCaller) GetLastUpdatedBlock(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "getLastUpdatedBlock") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetLastUpdatedBlock is a free data retrieval call binding the contract method 0x87c891bd. +// +// Solidity: function getLastUpdatedBlock() view returns(uint256) +func (_RoninValidatorSet *RoninValidatorSetSession) GetLastUpdatedBlock() (*big.Int, error) { + return _RoninValidatorSet.Contract.GetLastUpdatedBlock(&_RoninValidatorSet.CallOpts) +} + +// GetLastUpdatedBlock is a free data retrieval call binding the contract method 0x87c891bd. +// +// Solidity: function getLastUpdatedBlock() view returns(uint256) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) GetLastUpdatedBlock() (*big.Int, error) { + return _RoninValidatorSet.Contract.GetLastUpdatedBlock(&_RoninValidatorSet.CallOpts) +} + +// GetValidators is a free data retrieval call binding the contract method 0xb7ab4db5. +// +// Solidity: function getValidators() view returns(address[] _validatorList) +func (_RoninValidatorSet *RoninValidatorSetCaller) GetValidators(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "getValidators") + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +// GetValidators is a free data retrieval call binding the contract method 0xb7ab4db5. +// +// Solidity: function getValidators() view returns(address[] _validatorList) +func (_RoninValidatorSet *RoninValidatorSetSession) GetValidators() ([]common.Address, error) { + return _RoninValidatorSet.Contract.GetValidators(&_RoninValidatorSet.CallOpts) +} + +// GetValidators is a free data retrieval call binding the contract method 0xb7ab4db5. +// +// Solidity: function getValidators() view returns(address[] _validatorList) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) GetValidators() ([]common.Address, error) { + return _RoninValidatorSet.Contract.GetValidators(&_RoninValidatorSet.CallOpts) +} + +// GovernanceAdminContract is a free data retrieval call binding the contract method 0xea82f784. +// +// Solidity: function governanceAdminContract() view returns(address) +func (_RoninValidatorSet *RoninValidatorSetCaller) GovernanceAdminContract(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "governanceAdminContract") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// GovernanceAdminContract is a free data retrieval call binding the contract method 0xea82f784. +// +// Solidity: function governanceAdminContract() view returns(address) +func (_RoninValidatorSet *RoninValidatorSetSession) GovernanceAdminContract() (common.Address, error) { + return _RoninValidatorSet.Contract.GovernanceAdminContract(&_RoninValidatorSet.CallOpts) +} + +// GovernanceAdminContract is a free data retrieval call binding the contract method 0xea82f784. +// +// Solidity: function governanceAdminContract() view returns(address) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) GovernanceAdminContract() (common.Address, error) { + return _RoninValidatorSet.Contract.GovernanceAdminContract(&_RoninValidatorSet.CallOpts) +} + +// Jailed is a free data retrieval call binding the contract method 0x4454af9d. +// +// Solidity: function jailed(address[] _addrList) view returns(bool[] _result) +func (_RoninValidatorSet *RoninValidatorSetCaller) Jailed(opts *bind.CallOpts, _addrList []common.Address) ([]bool, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "jailed", _addrList) + + if err != nil { + return *new([]bool), err + } + + out0 := *abi.ConvertType(out[0], new([]bool)).(*[]bool) + + return out0, err + +} + +// Jailed is a free data retrieval call binding the contract method 0x4454af9d. +// +// Solidity: function jailed(address[] _addrList) view returns(bool[] _result) +func (_RoninValidatorSet *RoninValidatorSetSession) Jailed(_addrList []common.Address) ([]bool, error) { + return _RoninValidatorSet.Contract.Jailed(&_RoninValidatorSet.CallOpts, _addrList) +} + +// Jailed is a free data retrieval call binding the contract method 0x4454af9d. +// +// Solidity: function jailed(address[] _addrList) view returns(bool[] _result) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) Jailed(_addrList []common.Address) ([]bool, error) { + return _RoninValidatorSet.Contract.Jailed(&_RoninValidatorSet.CallOpts, _addrList) +} + +// NoPendingReward is a free data retrieval call binding the contract method 0x71e594b3. +// +// Solidity: function noPendingReward(address[] _addrList, uint256 _period) view returns(bool[] _result) +func (_RoninValidatorSet *RoninValidatorSetCaller) NoPendingReward(opts *bind.CallOpts, _addrList []common.Address, _period *big.Int) ([]bool, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "noPendingReward", _addrList, _period) + + if err != nil { + return *new([]bool), err + } + + out0 := *abi.ConvertType(out[0], new([]bool)).(*[]bool) + + return out0, err + +} + +// NoPendingReward is a free data retrieval call binding the contract method 0x71e594b3. +// +// Solidity: function noPendingReward(address[] _addrList, uint256 _period) view returns(bool[] _result) +func (_RoninValidatorSet *RoninValidatorSetSession) NoPendingReward(_addrList []common.Address, _period *big.Int) ([]bool, error) { + return _RoninValidatorSet.Contract.NoPendingReward(&_RoninValidatorSet.CallOpts, _addrList, _period) +} + +// NoPendingReward is a free data retrieval call binding the contract method 0x71e594b3. +// +// Solidity: function noPendingReward(address[] _addrList, uint256 _period) view returns(bool[] _result) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) NoPendingReward(_addrList []common.Address, _period *big.Int) ([]bool, error) { + return _RoninValidatorSet.Contract.NoPendingReward(&_RoninValidatorSet.CallOpts, _addrList, _period) +} + +// NumberOfBlocksInEpoch is a free data retrieval call binding the contract method 0x6aa1c2ef. +// +// Solidity: function numberOfBlocksInEpoch() view returns(uint256 _numberOfBlocks) +func (_RoninValidatorSet *RoninValidatorSetCaller) NumberOfBlocksInEpoch(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "numberOfBlocksInEpoch") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// NumberOfBlocksInEpoch is a free data retrieval call binding the contract method 0x6aa1c2ef. +// +// Solidity: function numberOfBlocksInEpoch() view returns(uint256 _numberOfBlocks) +func (_RoninValidatorSet *RoninValidatorSetSession) NumberOfBlocksInEpoch() (*big.Int, error) { + return _RoninValidatorSet.Contract.NumberOfBlocksInEpoch(&_RoninValidatorSet.CallOpts) +} + +// NumberOfBlocksInEpoch is a free data retrieval call binding the contract method 0x6aa1c2ef. +// +// Solidity: function numberOfBlocksInEpoch() view returns(uint256 _numberOfBlocks) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) NumberOfBlocksInEpoch() (*big.Int, error) { + return _RoninValidatorSet.Contract.NumberOfBlocksInEpoch(&_RoninValidatorSet.CallOpts) +} + +// NumberOfEpochsInPeriod is a free data retrieval call binding the contract method 0x5186dc7e. +// +// Solidity: function numberOfEpochsInPeriod() view returns(uint256 _numberOfEpochs) +func (_RoninValidatorSet *RoninValidatorSetCaller) NumberOfEpochsInPeriod(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "numberOfEpochsInPeriod") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// NumberOfEpochsInPeriod is a free data retrieval call binding the contract method 0x5186dc7e. +// +// Solidity: function numberOfEpochsInPeriod() view returns(uint256 _numberOfEpochs) +func (_RoninValidatorSet *RoninValidatorSetSession) NumberOfEpochsInPeriod() (*big.Int, error) { + return _RoninValidatorSet.Contract.NumberOfEpochsInPeriod(&_RoninValidatorSet.CallOpts) +} + +// NumberOfEpochsInPeriod is a free data retrieval call binding the contract method 0x5186dc7e. +// +// Solidity: function numberOfEpochsInPeriod() view returns(uint256 _numberOfEpochs) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) NumberOfEpochsInPeriod() (*big.Int, error) { + return _RoninValidatorSet.Contract.NumberOfEpochsInPeriod(&_RoninValidatorSet.CallOpts) +} + +// PeriodEndingAt is a free data retrieval call binding the contract method 0x25a6b529. +// +// Solidity: function periodEndingAt(uint256 _block) view returns(bool) +func (_RoninValidatorSet *RoninValidatorSetCaller) PeriodEndingAt(opts *bind.CallOpts, _block *big.Int) (bool, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "periodEndingAt", _block) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// PeriodEndingAt is a free data retrieval call binding the contract method 0x25a6b529. +// +// Solidity: function periodEndingAt(uint256 _block) view returns(bool) +func (_RoninValidatorSet *RoninValidatorSetSession) PeriodEndingAt(_block *big.Int) (bool, error) { + return _RoninValidatorSet.Contract.PeriodEndingAt(&_RoninValidatorSet.CallOpts, _block) +} + +// PeriodEndingAt is a free data retrieval call binding the contract method 0x25a6b529. +// +// Solidity: function periodEndingAt(uint256 _block) view returns(bool) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) PeriodEndingAt(_block *big.Int) (bool, error) { + return _RoninValidatorSet.Contract.PeriodEndingAt(&_RoninValidatorSet.CallOpts, _block) +} + +// PeriodOf is a free data retrieval call binding the contract method 0xf8549af9. +// +// Solidity: function periodOf(uint256 _block) view returns(uint256) +func (_RoninValidatorSet *RoninValidatorSetCaller) PeriodOf(opts *bind.CallOpts, _block *big.Int) (*big.Int, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "periodOf", _block) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// PeriodOf is a free data retrieval call binding the contract method 0xf8549af9. +// +// Solidity: function periodOf(uint256 _block) view returns(uint256) +func (_RoninValidatorSet *RoninValidatorSetSession) PeriodOf(_block *big.Int) (*big.Int, error) { + return _RoninValidatorSet.Contract.PeriodOf(&_RoninValidatorSet.CallOpts, _block) +} + +// PeriodOf is a free data retrieval call binding the contract method 0xf8549af9. +// +// Solidity: function periodOf(uint256 _block) view returns(uint256) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) PeriodOf(_block *big.Int) (*big.Int, error) { + return _RoninValidatorSet.Contract.PeriodOf(&_RoninValidatorSet.CallOpts, _block) +} + +// SlashDoubleSignAmount is a free data retrieval call binding the contract method 0x6d14c4e5. +// +// Solidity: function slashDoubleSignAmount() view returns(uint256) +func (_RoninValidatorSet *RoninValidatorSetCaller) SlashDoubleSignAmount(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "slashDoubleSignAmount") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// SlashDoubleSignAmount is a free data retrieval call binding the contract method 0x6d14c4e5. +// +// Solidity: function slashDoubleSignAmount() view returns(uint256) +func (_RoninValidatorSet *RoninValidatorSetSession) SlashDoubleSignAmount() (*big.Int, error) { + return _RoninValidatorSet.Contract.SlashDoubleSignAmount(&_RoninValidatorSet.CallOpts) +} + +// SlashDoubleSignAmount is a free data retrieval call binding the contract method 0x6d14c4e5. +// +// Solidity: function slashDoubleSignAmount() view returns(uint256) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) SlashDoubleSignAmount() (*big.Int, error) { + return _RoninValidatorSet.Contract.SlashDoubleSignAmount(&_RoninValidatorSet.CallOpts) +} + +// SlashFelonyAmount is a free data retrieval call binding the contract method 0xdfe484cb. +// +// Solidity: function slashFelonyAmount() view returns(uint256) +func (_RoninValidatorSet *RoninValidatorSetCaller) SlashFelonyAmount(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "slashFelonyAmount") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// SlashFelonyAmount is a free data retrieval call binding the contract method 0xdfe484cb. +// +// Solidity: function slashFelonyAmount() view returns(uint256) +func (_RoninValidatorSet *RoninValidatorSetSession) SlashFelonyAmount() (*big.Int, error) { + return _RoninValidatorSet.Contract.SlashFelonyAmount(&_RoninValidatorSet.CallOpts) +} + +// SlashFelonyAmount is a free data retrieval call binding the contract method 0xdfe484cb. +// +// Solidity: function slashFelonyAmount() view returns(uint256) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) SlashFelonyAmount() (*big.Int, error) { + return _RoninValidatorSet.Contract.SlashFelonyAmount(&_RoninValidatorSet.CallOpts) +} + +// SlashIndicatorContract is a free data retrieval call binding the contract method 0x5a08482d. +// +// Solidity: function slashIndicatorContract() view returns(address) +func (_RoninValidatorSet *RoninValidatorSetCaller) SlashIndicatorContract(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "slashIndicatorContract") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// SlashIndicatorContract is a free data retrieval call binding the contract method 0x5a08482d. +// +// Solidity: function slashIndicatorContract() view returns(address) +func (_RoninValidatorSet *RoninValidatorSetSession) SlashIndicatorContract() (common.Address, error) { + return _RoninValidatorSet.Contract.SlashIndicatorContract(&_RoninValidatorSet.CallOpts) +} + +// SlashIndicatorContract is a free data retrieval call binding the contract method 0x5a08482d. +// +// Solidity: function slashIndicatorContract() view returns(address) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) SlashIndicatorContract() (common.Address, error) { + return _RoninValidatorSet.Contract.SlashIndicatorContract(&_RoninValidatorSet.CallOpts) +} + +// StakingContract is a free data retrieval call binding the contract method 0xee99205c. +// +// Solidity: function stakingContract() view returns(address) +func (_RoninValidatorSet *RoninValidatorSetCaller) StakingContract(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "stakingContract") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// StakingContract is a free data retrieval call binding the contract method 0xee99205c. +// +// Solidity: function stakingContract() view returns(address) +func (_RoninValidatorSet *RoninValidatorSetSession) StakingContract() (common.Address, error) { + return _RoninValidatorSet.Contract.StakingContract(&_RoninValidatorSet.CallOpts) +} + +// StakingContract is a free data retrieval call binding the contract method 0xee99205c. +// +// Solidity: function stakingContract() view returns(address) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) StakingContract() (common.Address, error) { + return _RoninValidatorSet.Contract.StakingContract(&_RoninValidatorSet.CallOpts) +} + +// ValidatorCount is a free data retrieval call binding the contract method 0x0f43a677. +// +// Solidity: function validatorCount() view returns(uint256) +func (_RoninValidatorSet *RoninValidatorSetCaller) ValidatorCount(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "validatorCount") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ValidatorCount is a free data retrieval call binding the contract method 0x0f43a677. +// +// Solidity: function validatorCount() view returns(uint256) +func (_RoninValidatorSet *RoninValidatorSetSession) ValidatorCount() (*big.Int, error) { + return _RoninValidatorSet.Contract.ValidatorCount(&_RoninValidatorSet.CallOpts) +} + +// ValidatorCount is a free data retrieval call binding the contract method 0x0f43a677. +// +// Solidity: function validatorCount() view returns(uint256) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) ValidatorCount() (*big.Int, error) { + return _RoninValidatorSet.Contract.ValidatorCount(&_RoninValidatorSet.CallOpts) +} + +// Initialize is a paid mutator transaction binding the contract method 0xdf8fa430. +// +// Solidity: function initialize(address __governanceAdminContract, address __slashIndicatorContract, address __stakingContract, uint256 __maxValidatorNumber, uint256 __numberOfBlocksInEpoch, uint256 __numberOfEpochsInPeriod, uint256 _slashFelonyAmount, uint256 _slashDoubleSignAmount) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactor) Initialize(opts *bind.TransactOpts, __governanceAdminContract common.Address, __slashIndicatorContract common.Address, __stakingContract common.Address, __maxValidatorNumber *big.Int, __numberOfBlocksInEpoch *big.Int, __numberOfEpochsInPeriod *big.Int, _slashFelonyAmount *big.Int, _slashDoubleSignAmount *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.contract.Transact(opts, "initialize", __governanceAdminContract, __slashIndicatorContract, __stakingContract, __maxValidatorNumber, __numberOfBlocksInEpoch, __numberOfEpochsInPeriod, _slashFelonyAmount, _slashDoubleSignAmount) +} + +// Initialize is a paid mutator transaction binding the contract method 0xdf8fa430. +// +// Solidity: function initialize(address __governanceAdminContract, address __slashIndicatorContract, address __stakingContract, uint256 __maxValidatorNumber, uint256 __numberOfBlocksInEpoch, uint256 __numberOfEpochsInPeriod, uint256 _slashFelonyAmount, uint256 _slashDoubleSignAmount) returns() +func (_RoninValidatorSet *RoninValidatorSetSession) Initialize(__governanceAdminContract common.Address, __slashIndicatorContract common.Address, __stakingContract common.Address, __maxValidatorNumber *big.Int, __numberOfBlocksInEpoch *big.Int, __numberOfEpochsInPeriod *big.Int, _slashFelonyAmount *big.Int, _slashDoubleSignAmount *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.Initialize(&_RoninValidatorSet.TransactOpts, __governanceAdminContract, __slashIndicatorContract, __stakingContract, __maxValidatorNumber, __numberOfBlocksInEpoch, __numberOfEpochsInPeriod, _slashFelonyAmount, _slashDoubleSignAmount) +} + +// Initialize is a paid mutator transaction binding the contract method 0xdf8fa430. +// +// Solidity: function initialize(address __governanceAdminContract, address __slashIndicatorContract, address __stakingContract, uint256 __maxValidatorNumber, uint256 __numberOfBlocksInEpoch, uint256 __numberOfEpochsInPeriod, uint256 _slashFelonyAmount, uint256 _slashDoubleSignAmount) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) Initialize(__governanceAdminContract common.Address, __slashIndicatorContract common.Address, __stakingContract common.Address, __maxValidatorNumber *big.Int, __numberOfBlocksInEpoch *big.Int, __numberOfEpochsInPeriod *big.Int, _slashFelonyAmount *big.Int, _slashDoubleSignAmount *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.Initialize(&_RoninValidatorSet.TransactOpts, __governanceAdminContract, __slashIndicatorContract, __stakingContract, __maxValidatorNumber, __numberOfBlocksInEpoch, __numberOfEpochsInPeriod, _slashFelonyAmount, _slashDoubleSignAmount) +} + +// SlashDoubleSign is a paid mutator transaction binding the contract method 0x7ae46af3. +// +// Solidity: function slashDoubleSign(address _validatorAddr) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactor) SlashDoubleSign(opts *bind.TransactOpts, _validatorAddr common.Address) (*types.Transaction, error) { + return _RoninValidatorSet.contract.Transact(opts, "slashDoubleSign", _validatorAddr) +} + +// SlashDoubleSign is a paid mutator transaction binding the contract method 0x7ae46af3. +// +// Solidity: function slashDoubleSign(address _validatorAddr) returns() +func (_RoninValidatorSet *RoninValidatorSetSession) SlashDoubleSign(_validatorAddr common.Address) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SlashDoubleSign(&_RoninValidatorSet.TransactOpts, _validatorAddr) +} + +// SlashDoubleSign is a paid mutator transaction binding the contract method 0x7ae46af3. +// +// Solidity: function slashDoubleSign(address _validatorAddr) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) SlashDoubleSign(_validatorAddr common.Address) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SlashDoubleSign(&_RoninValidatorSet.TransactOpts, _validatorAddr) +} + +// SlashFelony is a paid mutator transaction binding the contract method 0x722d298f. +// +// Solidity: function slashFelony(address _validatorAddr) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactor) SlashFelony(opts *bind.TransactOpts, _validatorAddr common.Address) (*types.Transaction, error) { + return _RoninValidatorSet.contract.Transact(opts, "slashFelony", _validatorAddr) +} + +// SlashFelony is a paid mutator transaction binding the contract method 0x722d298f. +// +// Solidity: function slashFelony(address _validatorAddr) returns() +func (_RoninValidatorSet *RoninValidatorSetSession) SlashFelony(_validatorAddr common.Address) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SlashFelony(&_RoninValidatorSet.TransactOpts, _validatorAddr) +} + +// SlashFelony is a paid mutator transaction binding the contract method 0x722d298f. +// +// Solidity: function slashFelony(address _validatorAddr) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) SlashFelony(_validatorAddr common.Address) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SlashFelony(&_RoninValidatorSet.TransactOpts, _validatorAddr) +} + +// SlashMisdemeanor is a paid mutator transaction binding the contract method 0x3dc56e09. +// +// Solidity: function slashMisdemeanor(address _validatorAddr) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactor) SlashMisdemeanor(opts *bind.TransactOpts, _validatorAddr common.Address) (*types.Transaction, error) { + return _RoninValidatorSet.contract.Transact(opts, "slashMisdemeanor", _validatorAddr) +} + +// SlashMisdemeanor is a paid mutator transaction binding the contract method 0x3dc56e09. +// +// Solidity: function slashMisdemeanor(address _validatorAddr) returns() +func (_RoninValidatorSet *RoninValidatorSetSession) SlashMisdemeanor(_validatorAddr common.Address) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SlashMisdemeanor(&_RoninValidatorSet.TransactOpts, _validatorAddr) +} + +// SlashMisdemeanor is a paid mutator transaction binding the contract method 0x3dc56e09. +// +// Solidity: function slashMisdemeanor(address _validatorAddr) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) SlashMisdemeanor(_validatorAddr common.Address) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SlashMisdemeanor(&_RoninValidatorSet.TransactOpts, _validatorAddr) +} + +// SubmitBlockReward is a paid mutator transaction binding the contract method 0x52091f17. +// +// Solidity: function submitBlockReward() payable returns() +func (_RoninValidatorSet *RoninValidatorSetTransactor) SubmitBlockReward(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RoninValidatorSet.contract.Transact(opts, "submitBlockReward") +} + +// SubmitBlockReward is a paid mutator transaction binding the contract method 0x52091f17. +// +// Solidity: function submitBlockReward() payable returns() +func (_RoninValidatorSet *RoninValidatorSetSession) SubmitBlockReward() (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SubmitBlockReward(&_RoninValidatorSet.TransactOpts) +} + +// SubmitBlockReward is a paid mutator transaction binding the contract method 0x52091f17. +// +// Solidity: function submitBlockReward() payable returns() +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) SubmitBlockReward() (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SubmitBlockReward(&_RoninValidatorSet.TransactOpts) +} + +// WrapUpEpoch is a paid mutator transaction binding the contract method 0x72e46810. +// +// Solidity: function wrapUpEpoch() payable returns() +func (_RoninValidatorSet *RoninValidatorSetTransactor) WrapUpEpoch(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RoninValidatorSet.contract.Transact(opts, "wrapUpEpoch") +} + +// WrapUpEpoch is a paid mutator transaction binding the contract method 0x72e46810. +// +// Solidity: function wrapUpEpoch() payable returns() +func (_RoninValidatorSet *RoninValidatorSetSession) WrapUpEpoch() (*types.Transaction, error) { + return _RoninValidatorSet.Contract.WrapUpEpoch(&_RoninValidatorSet.TransactOpts) +} + +// WrapUpEpoch is a paid mutator transaction binding the contract method 0x72e46810. +// +// Solidity: function wrapUpEpoch() payable returns() +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) WrapUpEpoch() (*types.Transaction, error) { + return _RoninValidatorSet.Contract.WrapUpEpoch(&_RoninValidatorSet.TransactOpts) +} + +// RoninValidatorSetInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the RoninValidatorSet contract. +type RoninValidatorSetInitializedIterator struct { + Event *RoninValidatorSetInitialized // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RoninValidatorSetInitializedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetInitialized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetInitialized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RoninValidatorSetInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RoninValidatorSetInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RoninValidatorSetInitialized represents a Initialized event raised by the RoninValidatorSet contract. +type RoninValidatorSetInitialized struct { + Version uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_RoninValidatorSet *RoninValidatorSetFilterer) FilterInitialized(opts *bind.FilterOpts) (*RoninValidatorSetInitializedIterator, error) { + + logs, sub, err := _RoninValidatorSet.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &RoninValidatorSetInitializedIterator{contract: _RoninValidatorSet.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *RoninValidatorSetInitialized) (event.Subscription, error) { + + logs, sub, err := _RoninValidatorSet.contract.WatchLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RoninValidatorSetInitialized) + if err := _RoninValidatorSet.contract.UnpackLog(event, "Initialized", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseInitialized is a log parse operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_RoninValidatorSet *RoninValidatorSetFilterer) ParseInitialized(log types.Log) (*RoninValidatorSetInitialized, error) { + event := new(RoninValidatorSetInitialized) + if err := _RoninValidatorSet.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/consensus/consortium/generated_contracts/slash_indicator/slash_indicator.go b/consensus/consortium/generated_contracts/slash_indicator/slash_indicator.go new file mode 100644 index 0000000000..a40307adcc --- /dev/null +++ b/consensus/consortium/generated_contracts/slash_indicator/slash_indicator.go @@ -0,0 +1,731 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package slashIndicator + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// SlashIndicatorMetaData contains all meta data concerning the SlashIndicator contract. +var SlashIndicatorMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"contractIRoninValidatorSet\",\"name\":\"_validatorSetContract\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"validators\",\"type\":\"address[]\"}],\"name\":\"UnavailabilityIndicatorsReset\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"validator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"enumISlashIndicator.SlashType\",\"name\":\"slashType\",\"type\":\"uint8\"}],\"name\":\"ValidatorSlashed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"felonyThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"validator\",\"type\":\"address\"}],\"name\":\"getSlashIndicator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSlashThresholds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastSlashedBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"misdemeanorThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_validatorAddrs\",\"type\":\"address[]\"}],\"name\":\"resetCounters\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validatorAddr\",\"type\":\"address\"}],\"name\":\"slash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_valAddr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_evidence\",\"type\":\"bytes\"}],\"name\":\"slashDoubleSign\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"validatorContract\",\"outputs\":[{\"internalType\":\"contractIRoninValidatorSet\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60806040523480156200001157600080fd5b506040516200104d3803806200104d83398181016040528101906200003791906200010d565b6032600281905550609660038190555080600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506200013f565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620000c18262000094565b9050919050565b6000620000d582620000b4565b9050919050565b620000e781620000c8565b8114620000f357600080fd5b50565b6000815190506200010781620000dc565b92915050565b6000602082840312156200012657620001256200008f565b5b60006200013684828501620000f6565b91505092915050565b610efe806200014f6000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c80638256ace6116100665780638256ace614610120578063994390891461013f578063aef250be1461015d578063c96be4cb1461017b578063ec35fe721461019757610093565b806337c8dab914610098578063389f4f71146100c8578063518e463a146100e6578063567a372d14610102575b600080fd5b6100b260048036038101906100ad91906107e0565b6101b3565b6040516100bf9190610826565b60405180910390f35b6100d06101fb565b6040516100dd9190610826565b60405180910390f35b61010060048036038101906100fb91906108a6565b610201565b005b61010a6102aa565b6040516101179190610826565b60405180910390f35b6101286102b0565b604051610136929190610906565b60405180910390f35b6101476102c1565b604051610154919061098e565b60405180910390f35b6101656102e7565b6040516101729190610826565b60405180910390f35b610195600480360381019061019091906107e0565b6102ed565b005b6101b160048036038101906101ac91906109ff565b610605565b005b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60035481565b4173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461026f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161026690610acf565b60405180910390fd5b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102a190610b3b565b60405180910390fd5b60025481565b600080600254600354915091509091565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015481565b4173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461035b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161035290610acf565b60405180910390fd5b600154431161039f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161039690610bcd565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1603156105fb5760008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000815461042090610c1c565b9190508190559050600354810361051257600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663722d298f836040518263ffffffff1660e01b815260040161048c9190610c73565b600060405180830381600087803b1580156104a657600080fd5b505af11580156104ba573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff167f72b4cbc6db714fd31d4f3a8686c34df7b11819178ea38a792798f38a99d15e4a60026040516105059190610d05565b60405180910390a26105f9565b60025481036105f857600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633dc56e09836040518263ffffffff1660e01b81526004016105769190610c73565b600060405180830381600087803b15801561059057600080fd5b505af11580156105a4573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff167f72b4cbc6db714fd31d4f3a8686c34df7b11819178ea38a792798f38a99d15e4a60016040516105ef9190610d05565b60405180910390a25b5b505b4360018190555050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610695576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90610d92565b60405180910390fd5b61069f82826106a3565b5050565b60008282905003156107745760005b82829050811015610739576000808484848181106106d3576106d2610db2565b5b90506020020160208101906106e891906107e0565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009055808061073190610c1c565b9150506106b2565b507f9ae71e4f83d6019cd988ca4c38a696d015d5f6e41f3fd708fb746d2b672b4996828260405161076b929190610ea4565b60405180910390a15b5050565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006107ad82610782565b9050919050565b6107bd816107a2565b81146107c857600080fd5b50565b6000813590506107da816107b4565b92915050565b6000602082840312156107f6576107f5610778565b5b6000610804848285016107cb565b91505092915050565b6000819050919050565b6108208161080d565b82525050565b600060208201905061083b6000830184610817565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261086657610865610841565b5b8235905067ffffffffffffffff81111561088357610882610846565b5b60208301915083600182028301111561089f5761089e61084b565b5b9250929050565b6000806000604084860312156108bf576108be610778565b5b60006108cd868287016107cb565b935050602084013567ffffffffffffffff8111156108ee576108ed61077d565b5b6108fa86828701610850565b92509250509250925092565b600060408201905061091b6000830185610817565b6109286020830184610817565b9392505050565b6000819050919050565b600061095461094f61094a84610782565b61092f565b610782565b9050919050565b600061096682610939565b9050919050565b60006109788261095b565b9050919050565b6109888161096d565b82525050565b60006020820190506109a3600083018461097f565b92915050565b60008083601f8401126109bf576109be610841565b5b8235905067ffffffffffffffff8111156109dc576109db610846565b5b6020830191508360208202830111156109f8576109f761084b565b5b9250929050565b60008060208385031215610a1657610a15610778565b5b600083013567ffffffffffffffff811115610a3457610a3361077d565b5b610a40858286016109a9565b92509250509250929050565b600082825260208201905092915050565b7f536c617368496e64696361746f723a206d6574686f642063616c6c657220697360008201527f206e6f742074686520636f696e62617365000000000000000000000000000000602082015250565b6000610ab9603183610a4c565b9150610ac482610a5d565b604082019050919050565b60006020820190508181036000830152610ae881610aac565b9050919050565b7f4e6f7420696d706c656d656e7465640000000000000000000000000000000000600082015250565b6000610b25600f83610a4c565b9150610b3082610aef565b602082019050919050565b60006020820190508181036000830152610b5481610b18565b9050919050565b7f536c617368496e64696361746f723a2063616e6e6f7420736c6173682074776960008201527f636520696e206f6e6520626c6f636b0000000000000000000000000000000000602082015250565b6000610bb7602f83610a4c565b9150610bc282610b5b565b604082019050919050565b60006020820190508181036000830152610be681610baa565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610c278261080d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610c5957610c58610bed565b5b600182019050919050565b610c6d816107a2565b82525050565b6000602082019050610c886000830184610c64565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110610cce57610ccd610c8e565b5b50565b6000819050610cdf82610cbd565b919050565b6000610cef82610cd1565b9050919050565b610cff81610ce4565b82525050565b6000602082019050610d1a6000830184610cf6565b92915050565b7f536c617368496e64696361746f723a206d6574686f642063616c6c657220697360008201527f206e6f74207468652076616c696461746f7220636f6e74726163740000000000602082015250565b6000610d7c603b83610a4c565b9150610d8782610d20565b604082019050919050565b60006020820190508181036000830152610dab81610d6f565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082825260208201905092915050565b6000819050919050565b610e05816107a2565b82525050565b6000610e178383610dfc565b60208301905092915050565b6000610e3260208401846107cb565b905092915050565b6000602082019050919050565b6000610e538385610de1565b9350610e5e82610df2565b8060005b85811015610e9757610e748284610e23565b610e7e8882610e0b565b9750610e8983610e3a565b925050600181019050610e62565b5085925050509392505050565b60006020820190508181036000830152610ebf818486610e47565b9050939250505056fea264697066735822122091242cd808a850e5ec6d87e9be207e3ce6e1d7f067c64bbea66e01a4beca6a7b64736f6c63430008100033", +} + +// SlashIndicatorABI is the input ABI used to generate the binding from. +// Deprecated: Use SlashIndicatorMetaData.ABI instead. +var SlashIndicatorABI = SlashIndicatorMetaData.ABI + +// SlashIndicatorBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use SlashIndicatorMetaData.Bin instead. +var SlashIndicatorBin = SlashIndicatorMetaData.Bin + +// DeploySlashIndicator deploys a new Ethereum contract, binding an instance of SlashIndicator to it. +func DeploySlashIndicator(auth *bind.TransactOpts, backend bind.ContractBackend, _validatorSetContract common.Address) (common.Address, *types.Transaction, *SlashIndicator, error) { + parsed, err := SlashIndicatorMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(SlashIndicatorBin), backend, _validatorSetContract) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &SlashIndicator{SlashIndicatorCaller: SlashIndicatorCaller{contract: contract}, SlashIndicatorTransactor: SlashIndicatorTransactor{contract: contract}, SlashIndicatorFilterer: SlashIndicatorFilterer{contract: contract}}, nil +} + +// SlashIndicator is an auto generated Go binding around an Ethereum contract. +type SlashIndicator struct { + SlashIndicatorCaller // Read-only binding to the contract + SlashIndicatorTransactor // Write-only binding to the contract + SlashIndicatorFilterer // Log filterer for contract events +} + +// SlashIndicatorCaller is an auto generated read-only Go binding around an Ethereum contract. +type SlashIndicatorCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// SlashIndicatorTransactor is an auto generated write-only Go binding around an Ethereum contract. +type SlashIndicatorTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// SlashIndicatorFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type SlashIndicatorFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// SlashIndicatorSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type SlashIndicatorSession struct { + Contract *SlashIndicator // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// SlashIndicatorCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type SlashIndicatorCallerSession struct { + Contract *SlashIndicatorCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// SlashIndicatorTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type SlashIndicatorTransactorSession struct { + Contract *SlashIndicatorTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// SlashIndicatorRaw is an auto generated low-level Go binding around an Ethereum contract. +type SlashIndicatorRaw struct { + Contract *SlashIndicator // Generic contract binding to access the raw methods on +} + +// SlashIndicatorCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type SlashIndicatorCallerRaw struct { + Contract *SlashIndicatorCaller // Generic read-only contract binding to access the raw methods on +} + +// SlashIndicatorTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type SlashIndicatorTransactorRaw struct { + Contract *SlashIndicatorTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewSlashIndicator creates a new instance of SlashIndicator, bound to a specific deployed contract. +func NewSlashIndicator(address common.Address, backend bind.ContractBackend) (*SlashIndicator, error) { + contract, err := bindSlashIndicator(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &SlashIndicator{SlashIndicatorCaller: SlashIndicatorCaller{contract: contract}, SlashIndicatorTransactor: SlashIndicatorTransactor{contract: contract}, SlashIndicatorFilterer: SlashIndicatorFilterer{contract: contract}}, nil +} + +// NewSlashIndicatorCaller creates a new read-only instance of SlashIndicator, bound to a specific deployed contract. +func NewSlashIndicatorCaller(address common.Address, caller bind.ContractCaller) (*SlashIndicatorCaller, error) { + contract, err := bindSlashIndicator(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &SlashIndicatorCaller{contract: contract}, nil +} + +// NewSlashIndicatorTransactor creates a new write-only instance of SlashIndicator, bound to a specific deployed contract. +func NewSlashIndicatorTransactor(address common.Address, transactor bind.ContractTransactor) (*SlashIndicatorTransactor, error) { + contract, err := bindSlashIndicator(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &SlashIndicatorTransactor{contract: contract}, nil +} + +// NewSlashIndicatorFilterer creates a new log filterer instance of SlashIndicator, bound to a specific deployed contract. +func NewSlashIndicatorFilterer(address common.Address, filterer bind.ContractFilterer) (*SlashIndicatorFilterer, error) { + contract, err := bindSlashIndicator(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &SlashIndicatorFilterer{contract: contract}, nil +} + +// bindSlashIndicator binds a generic wrapper to an already deployed contract. +func bindSlashIndicator(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(SlashIndicatorABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_SlashIndicator *SlashIndicatorRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _SlashIndicator.Contract.SlashIndicatorCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_SlashIndicator *SlashIndicatorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _SlashIndicator.Contract.SlashIndicatorTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_SlashIndicator *SlashIndicatorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _SlashIndicator.Contract.SlashIndicatorTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_SlashIndicator *SlashIndicatorCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _SlashIndicator.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_SlashIndicator *SlashIndicatorTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _SlashIndicator.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_SlashIndicator *SlashIndicatorTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _SlashIndicator.Contract.contract.Transact(opts, method, params...) +} + +// FelonyThreshold is a free data retrieval call binding the contract method 0x389f4f71. +// +// Solidity: function felonyThreshold() view returns(uint256) +func (_SlashIndicator *SlashIndicatorCaller) FelonyThreshold(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _SlashIndicator.contract.Call(opts, &out, "felonyThreshold") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// FelonyThreshold is a free data retrieval call binding the contract method 0x389f4f71. +// +// Solidity: function felonyThreshold() view returns(uint256) +func (_SlashIndicator *SlashIndicatorSession) FelonyThreshold() (*big.Int, error) { + return _SlashIndicator.Contract.FelonyThreshold(&_SlashIndicator.CallOpts) +} + +// FelonyThreshold is a free data retrieval call binding the contract method 0x389f4f71. +// +// Solidity: function felonyThreshold() view returns(uint256) +func (_SlashIndicator *SlashIndicatorCallerSession) FelonyThreshold() (*big.Int, error) { + return _SlashIndicator.Contract.FelonyThreshold(&_SlashIndicator.CallOpts) +} + +// GetSlashIndicator is a free data retrieval call binding the contract method 0x37c8dab9. +// +// Solidity: function getSlashIndicator(address validator) view returns(uint256) +func (_SlashIndicator *SlashIndicatorCaller) GetSlashIndicator(opts *bind.CallOpts, validator common.Address) (*big.Int, error) { + var out []interface{} + err := _SlashIndicator.contract.Call(opts, &out, "getSlashIndicator", validator) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetSlashIndicator is a free data retrieval call binding the contract method 0x37c8dab9. +// +// Solidity: function getSlashIndicator(address validator) view returns(uint256) +func (_SlashIndicator *SlashIndicatorSession) GetSlashIndicator(validator common.Address) (*big.Int, error) { + return _SlashIndicator.Contract.GetSlashIndicator(&_SlashIndicator.CallOpts, validator) +} + +// GetSlashIndicator is a free data retrieval call binding the contract method 0x37c8dab9. +// +// Solidity: function getSlashIndicator(address validator) view returns(uint256) +func (_SlashIndicator *SlashIndicatorCallerSession) GetSlashIndicator(validator common.Address) (*big.Int, error) { + return _SlashIndicator.Contract.GetSlashIndicator(&_SlashIndicator.CallOpts, validator) +} + +// GetSlashThresholds is a free data retrieval call binding the contract method 0x8256ace6. +// +// Solidity: function getSlashThresholds() view returns(uint256, uint256) +func (_SlashIndicator *SlashIndicatorCaller) GetSlashThresholds(opts *bind.CallOpts) (*big.Int, *big.Int, error) { + var out []interface{} + err := _SlashIndicator.contract.Call(opts, &out, "getSlashThresholds") + + if err != nil { + return *new(*big.Int), *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + out1 := *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + + return out0, out1, err + +} + +// GetSlashThresholds is a free data retrieval call binding the contract method 0x8256ace6. +// +// Solidity: function getSlashThresholds() view returns(uint256, uint256) +func (_SlashIndicator *SlashIndicatorSession) GetSlashThresholds() (*big.Int, *big.Int, error) { + return _SlashIndicator.Contract.GetSlashThresholds(&_SlashIndicator.CallOpts) +} + +// GetSlashThresholds is a free data retrieval call binding the contract method 0x8256ace6. +// +// Solidity: function getSlashThresholds() view returns(uint256, uint256) +func (_SlashIndicator *SlashIndicatorCallerSession) GetSlashThresholds() (*big.Int, *big.Int, error) { + return _SlashIndicator.Contract.GetSlashThresholds(&_SlashIndicator.CallOpts) +} + +// LastSlashedBlock is a free data retrieval call binding the contract method 0xaef250be. +// +// Solidity: function lastSlashedBlock() view returns(uint256) +func (_SlashIndicator *SlashIndicatorCaller) LastSlashedBlock(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _SlashIndicator.contract.Call(opts, &out, "lastSlashedBlock") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// LastSlashedBlock is a free data retrieval call binding the contract method 0xaef250be. +// +// Solidity: function lastSlashedBlock() view returns(uint256) +func (_SlashIndicator *SlashIndicatorSession) LastSlashedBlock() (*big.Int, error) { + return _SlashIndicator.Contract.LastSlashedBlock(&_SlashIndicator.CallOpts) +} + +// LastSlashedBlock is a free data retrieval call binding the contract method 0xaef250be. +// +// Solidity: function lastSlashedBlock() view returns(uint256) +func (_SlashIndicator *SlashIndicatorCallerSession) LastSlashedBlock() (*big.Int, error) { + return _SlashIndicator.Contract.LastSlashedBlock(&_SlashIndicator.CallOpts) +} + +// MisdemeanorThreshold is a free data retrieval call binding the contract method 0x567a372d. +// +// Solidity: function misdemeanorThreshold() view returns(uint256) +func (_SlashIndicator *SlashIndicatorCaller) MisdemeanorThreshold(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _SlashIndicator.contract.Call(opts, &out, "misdemeanorThreshold") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// MisdemeanorThreshold is a free data retrieval call binding the contract method 0x567a372d. +// +// Solidity: function misdemeanorThreshold() view returns(uint256) +func (_SlashIndicator *SlashIndicatorSession) MisdemeanorThreshold() (*big.Int, error) { + return _SlashIndicator.Contract.MisdemeanorThreshold(&_SlashIndicator.CallOpts) +} + +// MisdemeanorThreshold is a free data retrieval call binding the contract method 0x567a372d. +// +// Solidity: function misdemeanorThreshold() view returns(uint256) +func (_SlashIndicator *SlashIndicatorCallerSession) MisdemeanorThreshold() (*big.Int, error) { + return _SlashIndicator.Contract.MisdemeanorThreshold(&_SlashIndicator.CallOpts) +} + +// ValidatorContract is a free data retrieval call binding the contract method 0x99439089. +// +// Solidity: function validatorContract() view returns(address) +func (_SlashIndicator *SlashIndicatorCaller) ValidatorContract(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _SlashIndicator.contract.Call(opts, &out, "validatorContract") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// ValidatorContract is a free data retrieval call binding the contract method 0x99439089. +// +// Solidity: function validatorContract() view returns(address) +func (_SlashIndicator *SlashIndicatorSession) ValidatorContract() (common.Address, error) { + return _SlashIndicator.Contract.ValidatorContract(&_SlashIndicator.CallOpts) +} + +// ValidatorContract is a free data retrieval call binding the contract method 0x99439089. +// +// Solidity: function validatorContract() view returns(address) +func (_SlashIndicator *SlashIndicatorCallerSession) ValidatorContract() (common.Address, error) { + return _SlashIndicator.Contract.ValidatorContract(&_SlashIndicator.CallOpts) +} + +// ResetCounters is a paid mutator transaction binding the contract method 0xec35fe72. +// +// Solidity: function resetCounters(address[] _validatorAddrs) returns() +func (_SlashIndicator *SlashIndicatorTransactor) ResetCounters(opts *bind.TransactOpts, _validatorAddrs []common.Address) (*types.Transaction, error) { + return _SlashIndicator.contract.Transact(opts, "resetCounters", _validatorAddrs) +} + +// ResetCounters is a paid mutator transaction binding the contract method 0xec35fe72. +// +// Solidity: function resetCounters(address[] _validatorAddrs) returns() +func (_SlashIndicator *SlashIndicatorSession) ResetCounters(_validatorAddrs []common.Address) (*types.Transaction, error) { + return _SlashIndicator.Contract.ResetCounters(&_SlashIndicator.TransactOpts, _validatorAddrs) +} + +// ResetCounters is a paid mutator transaction binding the contract method 0xec35fe72. +// +// Solidity: function resetCounters(address[] _validatorAddrs) returns() +func (_SlashIndicator *SlashIndicatorTransactorSession) ResetCounters(_validatorAddrs []common.Address) (*types.Transaction, error) { + return _SlashIndicator.Contract.ResetCounters(&_SlashIndicator.TransactOpts, _validatorAddrs) +} + +// Slash is a paid mutator transaction binding the contract method 0xc96be4cb. +// +// Solidity: function slash(address _validatorAddr) returns() +func (_SlashIndicator *SlashIndicatorTransactor) Slash(opts *bind.TransactOpts, _validatorAddr common.Address) (*types.Transaction, error) { + return _SlashIndicator.contract.Transact(opts, "slash", _validatorAddr) +} + +// Slash is a paid mutator transaction binding the contract method 0xc96be4cb. +// +// Solidity: function slash(address _validatorAddr) returns() +func (_SlashIndicator *SlashIndicatorSession) Slash(_validatorAddr common.Address) (*types.Transaction, error) { + return _SlashIndicator.Contract.Slash(&_SlashIndicator.TransactOpts, _validatorAddr) +} + +// Slash is a paid mutator transaction binding the contract method 0xc96be4cb. +// +// Solidity: function slash(address _validatorAddr) returns() +func (_SlashIndicator *SlashIndicatorTransactorSession) Slash(_validatorAddr common.Address) (*types.Transaction, error) { + return _SlashIndicator.Contract.Slash(&_SlashIndicator.TransactOpts, _validatorAddr) +} + +// SlashDoubleSign is a paid mutator transaction binding the contract method 0x518e463a. +// +// Solidity: function slashDoubleSign(address _valAddr, bytes _evidence) returns() +func (_SlashIndicator *SlashIndicatorTransactor) SlashDoubleSign(opts *bind.TransactOpts, _valAddr common.Address, _evidence []byte) (*types.Transaction, error) { + return _SlashIndicator.contract.Transact(opts, "slashDoubleSign", _valAddr, _evidence) +} + +// SlashDoubleSign is a paid mutator transaction binding the contract method 0x518e463a. +// +// Solidity: function slashDoubleSign(address _valAddr, bytes _evidence) returns() +func (_SlashIndicator *SlashIndicatorSession) SlashDoubleSign(_valAddr common.Address, _evidence []byte) (*types.Transaction, error) { + return _SlashIndicator.Contract.SlashDoubleSign(&_SlashIndicator.TransactOpts, _valAddr, _evidence) +} + +// SlashDoubleSign is a paid mutator transaction binding the contract method 0x518e463a. +// +// Solidity: function slashDoubleSign(address _valAddr, bytes _evidence) returns() +func (_SlashIndicator *SlashIndicatorTransactorSession) SlashDoubleSign(_valAddr common.Address, _evidence []byte) (*types.Transaction, error) { + return _SlashIndicator.Contract.SlashDoubleSign(&_SlashIndicator.TransactOpts, _valAddr, _evidence) +} + +// SlashIndicatorUnavailabilityIndicatorsResetIterator is returned from FilterUnavailabilityIndicatorsReset and is used to iterate over the raw logs and unpacked data for UnavailabilityIndicatorsReset events raised by the SlashIndicator contract. +type SlashIndicatorUnavailabilityIndicatorsResetIterator struct { + Event *SlashIndicatorUnavailabilityIndicatorsReset // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *SlashIndicatorUnavailabilityIndicatorsResetIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(SlashIndicatorUnavailabilityIndicatorsReset) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(SlashIndicatorUnavailabilityIndicatorsReset) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *SlashIndicatorUnavailabilityIndicatorsResetIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *SlashIndicatorUnavailabilityIndicatorsResetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// SlashIndicatorUnavailabilityIndicatorsReset represents a UnavailabilityIndicatorsReset event raised by the SlashIndicator contract. +type SlashIndicatorUnavailabilityIndicatorsReset struct { + Validators []common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUnavailabilityIndicatorsReset is a free log retrieval operation binding the contract event 0x9ae71e4f83d6019cd988ca4c38a696d015d5f6e41f3fd708fb746d2b672b4996. +// +// Solidity: event UnavailabilityIndicatorsReset(address[] validators) +func (_SlashIndicator *SlashIndicatorFilterer) FilterUnavailabilityIndicatorsReset(opts *bind.FilterOpts) (*SlashIndicatorUnavailabilityIndicatorsResetIterator, error) { + + logs, sub, err := _SlashIndicator.contract.FilterLogs(opts, "UnavailabilityIndicatorsReset") + if err != nil { + return nil, err + } + return &SlashIndicatorUnavailabilityIndicatorsResetIterator{contract: _SlashIndicator.contract, event: "UnavailabilityIndicatorsReset", logs: logs, sub: sub}, nil +} + +// WatchUnavailabilityIndicatorsReset is a free log subscription operation binding the contract event 0x9ae71e4f83d6019cd988ca4c38a696d015d5f6e41f3fd708fb746d2b672b4996. +// +// Solidity: event UnavailabilityIndicatorsReset(address[] validators) +func (_SlashIndicator *SlashIndicatorFilterer) WatchUnavailabilityIndicatorsReset(opts *bind.WatchOpts, sink chan<- *SlashIndicatorUnavailabilityIndicatorsReset) (event.Subscription, error) { + + logs, sub, err := _SlashIndicator.contract.WatchLogs(opts, "UnavailabilityIndicatorsReset") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(SlashIndicatorUnavailabilityIndicatorsReset) + if err := _SlashIndicator.contract.UnpackLog(event, "UnavailabilityIndicatorsReset", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseUnavailabilityIndicatorsReset is a log parse operation binding the contract event 0x9ae71e4f83d6019cd988ca4c38a696d015d5f6e41f3fd708fb746d2b672b4996. +// +// Solidity: event UnavailabilityIndicatorsReset(address[] validators) +func (_SlashIndicator *SlashIndicatorFilterer) ParseUnavailabilityIndicatorsReset(log types.Log) (*SlashIndicatorUnavailabilityIndicatorsReset, error) { + event := new(SlashIndicatorUnavailabilityIndicatorsReset) + if err := _SlashIndicator.contract.UnpackLog(event, "UnavailabilityIndicatorsReset", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// SlashIndicatorValidatorSlashedIterator is returned from FilterValidatorSlashed and is used to iterate over the raw logs and unpacked data for ValidatorSlashed events raised by the SlashIndicator contract. +type SlashIndicatorValidatorSlashedIterator struct { + Event *SlashIndicatorValidatorSlashed // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *SlashIndicatorValidatorSlashedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(SlashIndicatorValidatorSlashed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(SlashIndicatorValidatorSlashed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *SlashIndicatorValidatorSlashedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *SlashIndicatorValidatorSlashedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// SlashIndicatorValidatorSlashed represents a ValidatorSlashed event raised by the SlashIndicator contract. +type SlashIndicatorValidatorSlashed struct { + Validator common.Address + SlashType uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterValidatorSlashed is a free log retrieval operation binding the contract event 0x72b4cbc6db714fd31d4f3a8686c34df7b11819178ea38a792798f38a99d15e4a. +// +// Solidity: event ValidatorSlashed(address indexed validator, uint8 slashType) +func (_SlashIndicator *SlashIndicatorFilterer) FilterValidatorSlashed(opts *bind.FilterOpts, validator []common.Address) (*SlashIndicatorValidatorSlashedIterator, error) { + + var validatorRule []interface{} + for _, validatorItem := range validator { + validatorRule = append(validatorRule, validatorItem) + } + + logs, sub, err := _SlashIndicator.contract.FilterLogs(opts, "ValidatorSlashed", validatorRule) + if err != nil { + return nil, err + } + return &SlashIndicatorValidatorSlashedIterator{contract: _SlashIndicator.contract, event: "ValidatorSlashed", logs: logs, sub: sub}, nil +} + +// WatchValidatorSlashed is a free log subscription operation binding the contract event 0x72b4cbc6db714fd31d4f3a8686c34df7b11819178ea38a792798f38a99d15e4a. +// +// Solidity: event ValidatorSlashed(address indexed validator, uint8 slashType) +func (_SlashIndicator *SlashIndicatorFilterer) WatchValidatorSlashed(opts *bind.WatchOpts, sink chan<- *SlashIndicatorValidatorSlashed, validator []common.Address) (event.Subscription, error) { + + var validatorRule []interface{} + for _, validatorItem := range validator { + validatorRule = append(validatorRule, validatorItem) + } + + logs, sub, err := _SlashIndicator.contract.WatchLogs(opts, "ValidatorSlashed", validatorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(SlashIndicatorValidatorSlashed) + if err := _SlashIndicator.contract.UnpackLog(event, "ValidatorSlashed", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseValidatorSlashed is a log parse operation binding the contract event 0x72b4cbc6db714fd31d4f3a8686c34df7b11819178ea38a792798f38a99d15e4a. +// +// Solidity: event ValidatorSlashed(address indexed validator, uint8 slashType) +func (_SlashIndicator *SlashIndicatorFilterer) ParseValidatorSlashed(log types.Log) (*SlashIndicatorValidatorSlashed, error) { + event := new(SlashIndicatorValidatorSlashed) + if err := _SlashIndicator.contract.UnpackLog(event, "ValidatorSlashed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/consensus/consortium/generated_contracts/validators/main.go b/consensus/consortium/generated_contracts/validators/main.go deleted file mode 100644 index ce0bb5dbfd..0000000000 --- a/consensus/consortium/generated_contracts/validators/main.go +++ /dev/null @@ -1,418 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package validators - -import ( - "errors" - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription -) - -// ValidatorsMetaData contains all meta data concerning the Validators contract. -var ValidatorsMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_version\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"consensusAddress\",\"type\":\"address\"},{\"internalType\":\"addresspayable\",\"name\":\"feeAddress\",\"type\":\"address\"}],\"name\":\"addNode\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"currentValidatorSet\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"consensusAddress\",\"type\":\"address\"},{\"internalType\":\"addresspayable\",\"name\":\"feeAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"jailTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reward\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"currentValidatorSetMap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"valAddr\",\"type\":\"address\"}],\"name\":\"depositReward\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastUpdated\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getValidators\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateValidators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60806040526102586000806101000a81548161ffff021916908361ffff1602179055503480156200002f57600080fd5b5060405162000c3638038062000c3683398181016040528101906200005591906200019d565b80600190805190602001906200006d92919062000075565b505062000281565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282620000ad5760008555620000f9565b82601f10620000c857805160ff1916838001178555620000f9565b82800160010185558215620000f9579182015b82811115620000f8578251825591602001919060010190620000db565b5b5090506200010891906200010c565b5090565b5b80821115620001275760008160009055506001016200010d565b5090565b6000620001426200013c8462000216565b620001e2565b9050828152602081018484840111156200015b57600080fd5b6200016884828562000249565b509392505050565b600082601f8301126200018257600080fd5b8151620001948482602086016200012b565b91505092915050565b600060208284031215620001b057600080fd5b600082015167ffffffffffffffff811115620001cb57600080fd5b620001d98482850162000170565b91505092915050565b6000604051905081810181811067ffffffffffffffff821117156200020c576200020b6200027f565b5b8060405250919050565b600067ffffffffffffffff8211156200023457620002336200027f565b5b601f19601f8301169050602081019050919050565b60005b83811015620002695780820151818401526020810190506200024c565b8381111562000279576000848401525b50505050565bfe5b6109a580620002916000396000f3fe6080604052600436106100705760003560e01c806378121dd41161004e57806378121dd4146100e9578063ad3c9da614610114578063b7ab4db514610151578063db8ec38c1461017c57610070565b80632d497ba2146100755780636969a25c1461008c5780636ffa4dc1146100cd575b600080fd5b34801561008157600080fd5b5061008a6101a5565b005b34801561009857600080fd5b506100b360048036038101906100ae91906106c7565b610260565b6040516100c49594939291906107e2565b60405180910390f35b6100e760048036038101906100e29190610662565b6102e6565b005b3480156100f557600080fd5b506100fe610438565b60405161010b9190610877565b60405180910390f35b34801561012057600080fd5b5061013b60048036038101906101369190610662565b610442565b6040516101489190610877565b60405180910390f35b34801561015d57600080fd5b5061016661045a565b6040516101739190610835565b60405180910390f35b34801561018857600080fd5b506101a3600480360381019061019e919061068b565b610574565b005b4173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610213576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161020a90610857565b60405180910390fd5b6000439050600160008054906101000a900461ffff160361ffff1660008054906101000a900461ffff1661ffff16828161024957fe5b0614610255575061025e565b80600481905550505b565b6002818154811061027057600080fd5b90600052602060002090600502016000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060020154908060030154908060040154905085565b4173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610354576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161034b90610857565b60405180910390fd5b60005b6002805490508167ffffffffffffffff161015610433578173ffffffffffffffffffffffffffffffffffffffff1660028267ffffffffffffffff168154811061039c57fe5b906000526020600020906005020160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610426573460028267ffffffffffffffff168154811061040257fe5b90600052602060002090600502016004016000828254019250508190555050610435565b8080600101915050610357565b505b50565b6000600454905090565b60036020528060005260406000206000915090505481565b6060600060028054905067ffffffffffffffff8111801561047a57600080fd5b506040519080825280602002602001820160405280156104a95781602001602082028036833780820191505090505b50905060005b6002805490508167ffffffffffffffff16101561056c5760028167ffffffffffffffff16815481106104dd57fe5b906000526020600020906005020160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16828267ffffffffffffffff168151811061052557fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505080806001019150506104af565b508091505090565b600060026001816001815401808255809150500390600052602060002090600502019050828160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505050565b6000813590506106328161092a565b92915050565b60008135905061064781610941565b92915050565b60008135905061065c81610958565b92915050565b60006020828403121561067457600080fd5b600061068284828501610623565b91505092915050565b6000806040838503121561069e57600080fd5b60006106ac85828601610623565b92505060206106bd85828601610638565b9150509250929050565b6000602082840312156106d957600080fd5b60006106e78482850161064d565b91505092915050565b60006106fc8383610717565b60208301905092915050565b610711816108ee565b82525050565b610720816108dc565b82525050565b61072f816108dc565b82525050565b6000610740826108a2565b61074a81856108ba565b935061075583610892565b8060005b8381101561078657815161076d88826106f0565b9750610778836108ad565b925050600181019050610759565b5085935050505092915050565b60006107a06016836108cb565b91507f73656e646572206973206e6f7420636f696e62617365000000000000000000006000830152602082019050919050565b6107dc81610920565b82525050565b600060a0820190506107f76000830188610726565b6108046020830187610708565b61081160408301866107d3565b61081e60608301856107d3565b61082b60808301846107d3565b9695505050505050565b6000602082019050818103600083015261084f8184610735565b905092915050565b6000602082019050818103600083015261087081610793565b9050919050565b600060208201905061088c60008301846107d3565b92915050565b6000819050602082019050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b60006108e782610900565b9050919050565b60006108f982610900565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b610933816108dc565b811461093e57600080fd5b50565b61094a816108ee565b811461095557600080fd5b50565b61096181610920565b811461096c57600080fd5b5056fea264697066735822122015480192b8d148e024696a592a3fd5361e8c0abc4dc8ca3aebbc99c652f20abe64736f6c63430007060033", -} - -// ValidatorsABI is the input ABI used to generate the binding from. -// Deprecated: Use ValidatorsMetaData.ABI instead. -var ValidatorsABI = ValidatorsMetaData.ABI - -// ValidatorsBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use ValidatorsMetaData.Bin instead. -var ValidatorsBin = ValidatorsMetaData.Bin - -// DeployValidators deploys a new Ethereum contract, binding an instance of Validators to it. -func DeployValidators(auth *bind.TransactOpts, backend bind.ContractBackend, _version string) (common.Address, *types.Transaction, *Validators, error) { - parsed, err := ValidatorsMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } - - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(ValidatorsBin), backend, _version) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &Validators{ValidatorsCaller: ValidatorsCaller{contract: contract}, ValidatorsTransactor: ValidatorsTransactor{contract: contract}, ValidatorsFilterer: ValidatorsFilterer{contract: contract}}, nil -} - -// Validators is an auto generated Go binding around an Ethereum contract. -type Validators struct { - ValidatorsCaller // Read-only binding to the contract - ValidatorsTransactor // Write-only binding to the contract - ValidatorsFilterer // Log filterer for contract events -} - -// ValidatorsCaller is an auto generated read-only Go binding around an Ethereum contract. -type ValidatorsCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ValidatorsTransactor is an auto generated write-only Go binding around an Ethereum contract. -type ValidatorsTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ValidatorsFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type ValidatorsFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ValidatorsSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type ValidatorsSession struct { - Contract *Validators // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// ValidatorsCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type ValidatorsCallerSession struct { - Contract *ValidatorsCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// ValidatorsTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type ValidatorsTransactorSession struct { - Contract *ValidatorsTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// ValidatorsRaw is an auto generated low-level Go binding around an Ethereum contract. -type ValidatorsRaw struct { - Contract *Validators // Generic contract binding to access the raw methods on -} - -// ValidatorsCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type ValidatorsCallerRaw struct { - Contract *ValidatorsCaller // Generic read-only contract binding to access the raw methods on -} - -// ValidatorsTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type ValidatorsTransactorRaw struct { - Contract *ValidatorsTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewValidators creates a new instance of Validators, bound to a specific deployed contract. -func NewValidators(address common.Address, backend bind.ContractBackend) (*Validators, error) { - contract, err := bindValidators(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &Validators{ValidatorsCaller: ValidatorsCaller{contract: contract}, ValidatorsTransactor: ValidatorsTransactor{contract: contract}, ValidatorsFilterer: ValidatorsFilterer{contract: contract}}, nil -} - -// NewValidatorsCaller creates a new read-only instance of Validators, bound to a specific deployed contract. -func NewValidatorsCaller(address common.Address, caller bind.ContractCaller) (*ValidatorsCaller, error) { - contract, err := bindValidators(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &ValidatorsCaller{contract: contract}, nil -} - -// NewValidatorsTransactor creates a new write-only instance of Validators, bound to a specific deployed contract. -func NewValidatorsTransactor(address common.Address, transactor bind.ContractTransactor) (*ValidatorsTransactor, error) { - contract, err := bindValidators(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &ValidatorsTransactor{contract: contract}, nil -} - -// NewValidatorsFilterer creates a new log filterer instance of Validators, bound to a specific deployed contract. -func NewValidatorsFilterer(address common.Address, filterer bind.ContractFilterer) (*ValidatorsFilterer, error) { - contract, err := bindValidators(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &ValidatorsFilterer{contract: contract}, nil -} - -// bindValidators binds a generic wrapper to an already deployed contract. -func bindValidators(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(ValidatorsABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Validators *ValidatorsRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Validators.Contract.ValidatorsCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Validators *ValidatorsRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Validators.Contract.ValidatorsTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Validators *ValidatorsRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Validators.Contract.ValidatorsTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Validators *ValidatorsCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Validators.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Validators *ValidatorsTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Validators.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Validators *ValidatorsTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Validators.Contract.contract.Transact(opts, method, params...) -} - -// CurrentValidatorSet is a free data retrieval call binding the contract method 0x6969a25c. -// -// Solidity: function currentValidatorSet(uint256 ) view returns(address consensusAddress, address feeAddress, uint256 totalAmount, uint256 jailTime, uint256 reward) -func (_Validators *ValidatorsCaller) CurrentValidatorSet(opts *bind.CallOpts, arg0 *big.Int) (struct { - ConsensusAddress common.Address - FeeAddress common.Address - TotalAmount *big.Int - JailTime *big.Int - Reward *big.Int -}, error) { - var out []interface{} - err := _Validators.contract.Call(opts, &out, "currentValidatorSet", arg0) - - outstruct := new(struct { - ConsensusAddress common.Address - FeeAddress common.Address - TotalAmount *big.Int - JailTime *big.Int - Reward *big.Int - }) - if err != nil { - return *outstruct, err - } - - outstruct.ConsensusAddress = *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - outstruct.FeeAddress = *abi.ConvertType(out[1], new(common.Address)).(*common.Address) - outstruct.TotalAmount = *abi.ConvertType(out[2], new(*big.Int)).(**big.Int) - outstruct.JailTime = *abi.ConvertType(out[3], new(*big.Int)).(**big.Int) - outstruct.Reward = *abi.ConvertType(out[4], new(*big.Int)).(**big.Int) - - return *outstruct, err - -} - -// CurrentValidatorSet is a free data retrieval call binding the contract method 0x6969a25c. -// -// Solidity: function currentValidatorSet(uint256 ) view returns(address consensusAddress, address feeAddress, uint256 totalAmount, uint256 jailTime, uint256 reward) -func (_Validators *ValidatorsSession) CurrentValidatorSet(arg0 *big.Int) (struct { - ConsensusAddress common.Address - FeeAddress common.Address - TotalAmount *big.Int - JailTime *big.Int - Reward *big.Int -}, error) { - return _Validators.Contract.CurrentValidatorSet(&_Validators.CallOpts, arg0) -} - -// CurrentValidatorSet is a free data retrieval call binding the contract method 0x6969a25c. -// -// Solidity: function currentValidatorSet(uint256 ) view returns(address consensusAddress, address feeAddress, uint256 totalAmount, uint256 jailTime, uint256 reward) -func (_Validators *ValidatorsCallerSession) CurrentValidatorSet(arg0 *big.Int) (struct { - ConsensusAddress common.Address - FeeAddress common.Address - TotalAmount *big.Int - JailTime *big.Int - Reward *big.Int -}, error) { - return _Validators.Contract.CurrentValidatorSet(&_Validators.CallOpts, arg0) -} - -// CurrentValidatorSetMap is a free data retrieval call binding the contract method 0xad3c9da6. -// -// Solidity: function currentValidatorSetMap(address ) view returns(uint256) -func (_Validators *ValidatorsCaller) CurrentValidatorSetMap(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { - var out []interface{} - err := _Validators.contract.Call(opts, &out, "currentValidatorSetMap", arg0) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// CurrentValidatorSetMap is a free data retrieval call binding the contract method 0xad3c9da6. -// -// Solidity: function currentValidatorSetMap(address ) view returns(uint256) -func (_Validators *ValidatorsSession) CurrentValidatorSetMap(arg0 common.Address) (*big.Int, error) { - return _Validators.Contract.CurrentValidatorSetMap(&_Validators.CallOpts, arg0) -} - -// CurrentValidatorSetMap is a free data retrieval call binding the contract method 0xad3c9da6. -// -// Solidity: function currentValidatorSetMap(address ) view returns(uint256) -func (_Validators *ValidatorsCallerSession) CurrentValidatorSetMap(arg0 common.Address) (*big.Int, error) { - return _Validators.Contract.CurrentValidatorSetMap(&_Validators.CallOpts, arg0) -} - -// GetLastUpdated is a free data retrieval call binding the contract method 0x78121dd4. -// -// Solidity: function getLastUpdated() view returns(uint256) -func (_Validators *ValidatorsCaller) GetLastUpdated(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Validators.contract.Call(opts, &out, "getLastUpdated") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// GetLastUpdated is a free data retrieval call binding the contract method 0x78121dd4. -// -// Solidity: function getLastUpdated() view returns(uint256) -func (_Validators *ValidatorsSession) GetLastUpdated() (*big.Int, error) { - return _Validators.Contract.GetLastUpdated(&_Validators.CallOpts) -} - -// GetLastUpdated is a free data retrieval call binding the contract method 0x78121dd4. -// -// Solidity: function getLastUpdated() view returns(uint256) -func (_Validators *ValidatorsCallerSession) GetLastUpdated() (*big.Int, error) { - return _Validators.Contract.GetLastUpdated(&_Validators.CallOpts) -} - -// GetValidators is a free data retrieval call binding the contract method 0xb7ab4db5. -// -// Solidity: function getValidators() view returns(address[]) -func (_Validators *ValidatorsCaller) GetValidators(opts *bind.CallOpts) ([]common.Address, error) { - var out []interface{} - err := _Validators.contract.Call(opts, &out, "getValidators") - - if err != nil { - return *new([]common.Address), err - } - - out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) - - return out0, err - -} - -// GetValidators is a free data retrieval call binding the contract method 0xb7ab4db5. -// -// Solidity: function getValidators() view returns(address[]) -func (_Validators *ValidatorsSession) GetValidators() ([]common.Address, error) { - return _Validators.Contract.GetValidators(&_Validators.CallOpts) -} - -// GetValidators is a free data retrieval call binding the contract method 0xb7ab4db5. -// -// Solidity: function getValidators() view returns(address[]) -func (_Validators *ValidatorsCallerSession) GetValidators() ([]common.Address, error) { - return _Validators.Contract.GetValidators(&_Validators.CallOpts) -} - -// AddNode is a paid mutator transaction binding the contract method 0xdb8ec38c. -// -// Solidity: function addNode(address consensusAddress, address feeAddress) returns() -func (_Validators *ValidatorsTransactor) AddNode(opts *bind.TransactOpts, consensusAddress common.Address, feeAddress common.Address) (*types.Transaction, error) { - return _Validators.contract.Transact(opts, "addNode", consensusAddress, feeAddress) -} - -// AddNode is a paid mutator transaction binding the contract method 0xdb8ec38c. -// -// Solidity: function addNode(address consensusAddress, address feeAddress) returns() -func (_Validators *ValidatorsSession) AddNode(consensusAddress common.Address, feeAddress common.Address) (*types.Transaction, error) { - return _Validators.Contract.AddNode(&_Validators.TransactOpts, consensusAddress, feeAddress) -} - -// AddNode is a paid mutator transaction binding the contract method 0xdb8ec38c. -// -// Solidity: function addNode(address consensusAddress, address feeAddress) returns() -func (_Validators *ValidatorsTransactorSession) AddNode(consensusAddress common.Address, feeAddress common.Address) (*types.Transaction, error) { - return _Validators.Contract.AddNode(&_Validators.TransactOpts, consensusAddress, feeAddress) -} - -// DepositReward is a paid mutator transaction binding the contract method 0x6ffa4dc1. -// -// Solidity: function depositReward(address valAddr) payable returns() -func (_Validators *ValidatorsTransactor) DepositReward(opts *bind.TransactOpts, valAddr common.Address) (*types.Transaction, error) { - return _Validators.contract.Transact(opts, "depositReward", valAddr) -} - -// DepositReward is a paid mutator transaction binding the contract method 0x6ffa4dc1. -// -// Solidity: function depositReward(address valAddr) payable returns() -func (_Validators *ValidatorsSession) DepositReward(valAddr common.Address) (*types.Transaction, error) { - return _Validators.Contract.DepositReward(&_Validators.TransactOpts, valAddr) -} - -// DepositReward is a paid mutator transaction binding the contract method 0x6ffa4dc1. -// -// Solidity: function depositReward(address valAddr) payable returns() -func (_Validators *ValidatorsTransactorSession) DepositReward(valAddr common.Address) (*types.Transaction, error) { - return _Validators.Contract.DepositReward(&_Validators.TransactOpts, valAddr) -} - -// UpdateValidators is a paid mutator transaction binding the contract method 0x2d497ba2. -// -// Solidity: function updateValidators() returns() -func (_Validators *ValidatorsTransactor) UpdateValidators(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Validators.contract.Transact(opts, "updateValidators") -} - -// UpdateValidators is a paid mutator transaction binding the contract method 0x2d497ba2. -// -// Solidity: function updateValidators() returns() -func (_Validators *ValidatorsSession) UpdateValidators() (*types.Transaction, error) { - return _Validators.Contract.UpdateValidators(&_Validators.TransactOpts) -} - -// UpdateValidators is a paid mutator transaction binding the contract method 0x2d497ba2. -// -// Solidity: function updateValidators() returns() -func (_Validators *ValidatorsTransactorSession) UpdateValidators() (*types.Transaction, error) { - return _Validators.Contract.UpdateValidators(&_Validators.TransactOpts) -} diff --git a/consensus/consortium/v1/consortium.go b/consensus/consortium/v1/consortium.go index a2236df574..f4009af70f 100644 --- a/consensus/consortium/v1/consortium.go +++ b/consensus/consortium/v1/consortium.go @@ -558,7 +558,7 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head SignTxFn: c.signTxFn, EthAPI: c.ethAPI, } - if err := c.contract.UpdateValidators(transactOpts); err != nil { + if err := c.contract.WrapUpEpoch(transactOpts); err != nil { log.Error("Failed to update validators", "err", err) } // should not happen. Once happen, stop the node is better than broadcast the block diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index 9a4302df76..a5e2f5db20 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -581,8 +581,7 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H } } if !signedRecently { - log.Trace("slash validator", "block hash", header.Hash(), "address", spoiledVal) - err = c.contract.Slash(spoiledVal, transactOpts) + err = c.contract.Slash(transactOpts, spoiledVal) if err != nil { // it is possible that slash validator failed because of the slash channel is disabled. log.Error("slash validator failed", "block hash", header.Hash(), "address", spoiledVal) @@ -591,12 +590,12 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H } if header.Number.Uint64()%c.config.Epoch == c.config.Epoch-1 { - if err := c.contract.UpdateValidators(transactOpts); err != nil { + if err := c.contract.WrapUpEpoch(transactOpts); err != nil { log.Error("Failed to update validators", "err", err) } } - err = c.contract.DistributeRewards(header.Coinbase, transactOpts) + err = c.contract.SubmitBlockReward(transactOpts) if err != nil { return err } @@ -650,21 +649,21 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head } } if !signedRecently { - err = c.contract.Slash(spoiledVal, transactOpts) + err = c.contract.Slash(transactOpts, spoiledVal) if err != nil { // it is possible that slash validator failed because of the slash channel is disabled. - log.Error("slash validator failed", "block hash", header.Hash(), "address", spoiledVal) + log.Error("Slash validator failed", "block hash", header.Hash(), "address", spoiledVal, "error", err) } } } if header.Number.Uint64()%c.config.Epoch == c.config.Epoch-1 { - if err := c.contract.UpdateValidators(transactOpts); err != nil { - log.Error("Failed to update validators", "err", err) + if err := c.contract.WrapUpEpoch(transactOpts); err != nil { + log.Error("Wrap up epoch failed", "block hash", header.Hash(), "error", err) } } - err := c.contract.DistributeRewards(c.val, transactOpts) + err := c.contract.SubmitBlockReward(transactOpts) if err != nil { return nil, nil, err } diff --git a/params/config.go b/params/config.go index 79d704de54..dcfd1d4321 100644 --- a/params/config.go +++ b/params/config.go @@ -420,7 +420,8 @@ func (c *ConsortiumConfig) String() string { } type ConsortiumV2Contracts struct { - ValidatorSC common.Address `json:"validatorSC"` + RoninValidatorSet common.Address `json:"roninValidatorSet"` + SlashIndicator common.Address `json:"slashIndicator"` } func (c *ConsortiumV2Contracts) IsSystemContract(address common.Address) bool { @@ -447,11 +448,17 @@ func (c *ChainConfig) String() string { default: engine = "unknown" } - validatorSC := common.HexToAddress("") + roninValidatorSetSC := common.HexToAddress("") if c.ConsortiumV2Contracts != nil { - validatorSC = c.ConsortiumV2Contracts.ValidatorSC + roninValidatorSetSC = c.ConsortiumV2Contracts.RoninValidatorSet } - return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Odysseus: %v, Fenix: %v, Muir Glacier: %v, Berlin: %v, London: %v, Arrow Glacier: %v, Engine: %v, Blacklist Contract: %v, Fenix Validator Contract: %v, ConsortiumV2: %v, ConsortiumV2.ValidatorSC: %v}", + + slashIndicatorSC := common.HexToAddress("") + if c.ConsortiumV2Contracts != nil { + slashIndicatorSC = c.ConsortiumV2Contracts.SlashIndicator + } + + return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Odysseus: %v, Fenix: %v, Muir Glacier: %v, Berlin: %v, London: %v, Arrow Glacier: %v, Engine: %v, Blacklist Contract: %v, Fenix Validator Contract: %v, ConsortiumV2: %v, ConsortiumV2.RoninValidatorSet: %v, ConsortiumV2.SlashIndicator: %v}", c.ChainID, c.HomesteadBlock, c.DAOForkBlock, @@ -473,7 +480,8 @@ func (c *ChainConfig) String() string { c.BlacklistContractAddress, c.FenixValidatorContractAddress, c.ConsortiumV2Block, - validatorSC.Hex(), + roninValidatorSetSC.Hex(), + slashIndicatorSC.Hex(), ) } From 12f331ceb1e78d13090c3578a6f468de1668598f Mon Sep 17 00:00:00 2001 From: minh-bq <97180373+minh-bq@users.noreply.github.com> Date: Tue, 13 Sep 2022 16:38:44 +0700 Subject: [PATCH 28/52] Run FinalizeAndAssemble only on validator node (#122) We accept that the system transactions will not be in the pending state so it is unnecessary to call FinalizeAndAssemble in non-validator node. Move this call to be called only on validator node --- miner/worker.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/miner/worker.go b/miner/worker.go index 7900abb282..61402414a9 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -1031,13 +1031,15 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) // commit runs any post-transaction state modifications, assembles the final block // and commits new work if consensus engine is running. func (w *worker) commit(uncles []*types.Header, interval func(), update bool, start time.Time) error { - // Deep copy receipts here to avoid interaction between different tasks. - s := w.current.state.Copy() - block, receipts, err := w.engine.FinalizeAndAssemble(w.chain, w.current.header, s, w.current.txs, uncles, w.current.receipts) - if err != nil { - return err - } if w.isRunning() { + // Deep copy receipts here to avoid interaction between different tasks. + receiptsCpy := copyReceipts(w.current.receipts) + s := w.current.state.Copy() + block, receipts, err := w.engine.FinalizeAndAssemble(w.chain, w.current.header, s, w.current.txs, uncles, receiptsCpy) + if err != nil { + return err + } + if interval != nil { interval() } From 0e3bdff10adb748742584a9bb9213641699afa28 Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Tue, 13 Sep 2022 16:39:00 +0700 Subject: [PATCH 29/52] fix: verify signer on v1 (#123) --- consensus/consortium/v1/consortium.go | 28 +++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/consensus/consortium/v1/consortium.go b/consensus/consortium/v1/consortium.go index f4009af70f..41218b56a9 100644 --- a/consensus/consortium/v1/consortium.go +++ b/consensus/consortium/v1/consortium.go @@ -410,21 +410,25 @@ func (c *Consortium) verifySeal(chain consensus.ChainHeaderReader, header *types return errWrongCoinbase } - validators, err := c.getValidatorsFromLastCheckpoint(chain, number-1, nil) - if err != nil { - return err - } + //validators, err := c.getValidatorsFromLastCheckpoint(chain, number-1, nil) + //if err != nil { + // return err + //} + validators := snap.SignerList // If we're amongst the recent signers, wait for the next block - for seen, recent := range snap.Recents { - if recent == signer { - // Signer is among recents, only wait if the current block doesn't shift it out - if limit := uint64(len(validators)/2 + 1); seen > number-limit { - return errors.New("signed recently, must wait for others") - } - } + //for seen, recent := range snap.Recents { + // if recent == signer { + // // Signer is among recents, only wait if the current block doesn't shift it out + // if limit := uint64(len(validators)/2 + 1); seen > number-limit { + // return errors.New("signed recently, must wait for others") + // } + // } + //} + + if _, ok := snap.SignerSet[signer]; !ok { + return errUnauthorizedSigner } - // Ensure that the difficulty corresponds to the turn-ness of the signer inturn := c.signerInTurn(signer, header.Number.Uint64(), validators) if inturn && header.Difficulty.Cmp(diffInTurn) != 0 { From 5bd6e4d3ae0890ea2a11107f9b5f1eb476c4e532 Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Fri, 16 Sep 2022 13:07:52 +0700 Subject: [PATCH 30/52] chore: fix missing signTxFn, clear outdated recents, check missing tx (#125) * chore: fix missing signTxFn, clear outdate recents, check missing tx in state_processor * chore: check tx.To instead of tx --- consensus/consortium/common/contract.go | 8 ++++++-- consensus/consortium/common/utils.go | 19 +++++++++++++++++++ consensus/consortium/common/utils_test.go | 17 +++++++++++++++++ consensus/consortium/v2/consortium.go | 6 +++--- core/state_processor.go | 5 +++-- 5 files changed, 48 insertions(+), 7 deletions(-) diff --git a/consensus/consortium/common/contract.go b/consensus/consortium/common/contract.go index a510f7a94b..f26b356a87 100644 --- a/consensus/consortium/common/contract.go +++ b/consensus/consortium/common/contract.go @@ -38,6 +38,10 @@ func getTransactionOpts(from common.Address, nonce uint64, chainId *big.Int, sig Nonce: new(big.Int).SetUint64(nonce), NoSend: true, Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) { + if signTxFn == nil { + return tx, nil + } + return signTxFn(accounts.Account{Address: from}, tx, chainId) }, } @@ -148,7 +152,7 @@ func (c *ContractIntegrator) SubmitBlockReward(opts *ApplyTransactOpts) error { } func (c *ContractIntegrator) Slash(opts *ApplyTransactOpts, spoiledValidator common.Address) error { - log.Info("Slash validator", "block hash", opts.Header.Hash(), "address", spoiledValidator) + log.Warn("Slash validator", "number", opts.Header.Number.Uint64(), "coinbase", c.coinbase.Hex(), "spoiled", spoiledValidator.Hex()) nonce := opts.State.GetNonce(c.coinbase) tx, err := c.slashIndicatorSC.Slash(getTransactionOpts(c.coinbase, nonce, c.chainId, c.signTxFn), spoiledValidator) @@ -174,7 +178,7 @@ func (c *ContractIntegrator) Slash(opts *ApplyTransactOpts, spoiledValidator com return err } - return err + return nil } type ApplyMessageOpts struct { diff --git a/consensus/consortium/common/utils.go b/consensus/consortium/common/utils.go index 003c1d488a..fa41157898 100644 --- a/consensus/consortium/common/utils.go +++ b/consensus/consortium/common/utils.go @@ -2,6 +2,7 @@ package common import ( "github.com/ethereum/go-ethereum/common" + "sort" ) // ExtractAddressFromBytes extracts validators' address from extra data in header @@ -39,3 +40,21 @@ func SignerInList(signer common.Address, validators []common.Address) bool { } return false } + +func RemoveOutdatedRecents(recents map[uint64]common.Address, currentBlock uint64) map[uint64]common.Address { + var blocks []uint64 + for n, _ := range recents { + blocks = append(blocks, n) + } + sort.Slice(blocks, func(i, j int) bool { return blocks[i] > blocks[j] }) + + newRecents := make(map[uint64]common.Address) + for _, n := range blocks { + if currentBlock == n { + newRecents[n] = recents[n] + } + currentBlock -= 1 + } + + return newRecents +} diff --git a/consensus/consortium/common/utils_test.go b/consensus/consortium/common/utils_test.go index d91658ab41..2f028c9a0f 100644 --- a/consensus/consortium/common/utils_test.go +++ b/consensus/consortium/common/utils_test.go @@ -47,3 +47,20 @@ func TestCompareSignersLists(t *testing.T) { t.Errorf("Output %t not equal to expected %t", false, true) } } + +func TestRemoveInvalidRecents(t *testing.T) { + recents := map[uint64]common.Address{ + 7302958: common.HexToAddress("0xAfB9554299491a34d303f2C5A91bebB162f6B2Cf"), + 7305269: common.HexToAddress("0x3B9F2587d55E96276B09b258ac909D809961F6C2"), + 7408557: common.HexToAddress("0xB6bc5bc0410773A3F86B1537ce7495C52e38f88B"), + 7408558: common.HexToAddress("0x3B9F2587d55E96276B09b258ac909D809961F6C2"), + } + actual := RemoveOutdatedRecents(recents, 7408559) + expected := map[uint64]common.Address{ + 7408557: common.HexToAddress("0xB6bc5bc0410773A3F86B1537ce7495C52e38f88B"), + 7408558: common.HexToAddress("0x3B9F2587d55E96276B09b258ac909D809961F6C2"), + } + if !reflect.DeepEqual(expected, actual) { + t.Errorf("Expect %v but got %v", expected, actual) + } +} diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index a5e2f5db20..f3a13a8015 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -349,7 +349,8 @@ func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64, snap = newSnapshot(c.config, c.signatures, number, hash, validators, c.ethAPI) // get recents from v1 if number is end of v1 if c.chainConfig.IsOnConsortiumV2(big.NewInt(0).SetUint64(number + 1)) { - recents := c.v1.GetRecents(chain, number) + recents := consortiumCommon.RemoveOutdatedRecents(c.v1.GetRecents(chain, number), number) + if recents != nil { log.Info("adding previous recents to current snapshot", "number", number, "hash", hash.Hex(), "recents", recents) snap.Recents = recents @@ -747,8 +748,7 @@ func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, if recent == val { // Signer is among recents, only wait if the current block doesn't shift it out if limit := uint64(len(snap.Validators)/2 + 1); number < limit || seen > number-limit { - log.Info("Signed recently, must wait for others") - return nil + return errors.New("signed recently, must wait for others") } } } diff --git a/core/state_processor.go b/core/state_processor.go index e853d7a624..2b035e5c59 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -96,8 +96,9 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg } } - if p.config.ConsortiumV2Contracts != nil && p.config.IsOnConsortiumV2(big.NewInt(int64(block.NumberU64()+1))) && - p.config.ConsortiumV2Contracts.IsSystemContract(*tx.To()) { + hasConsortiumV2Contracts := p.config.ConsortiumV2Contracts != nil + isConsortiumV2 := p.config.IsOnConsortiumV2(big.NewInt(int64(block.NumberU64() + 1))) + if hasConsortiumV2Contracts && isConsortiumV2 && tx.To() != nil && p.config.ConsortiumV2Contracts.IsSystemContract(*tx.To()) { systemTxs = append(systemTxs, tx) continue } From 9fcf0434627bb778ecc6146fec236deec0835087 Mon Sep 17 00:00:00 2001 From: minh-bq <97180373+minh-bq@users.noreply.github.com> Date: Fri, 16 Sep 2022 15:58:35 +0700 Subject: [PATCH 31/52] Make copy of block header when passing it to FinalizeAndAssemble (#126) As default, an empty block without applying any transactions in transaction pool is committed for sealing. Later, if there is no pending transactions in pool, that empty block is inserted. Otherwise, another block is committed. As we currently pass block header as a pointer to FinalizeAndAssemble, that block header can be edited twice because it goes through FinalizeAndAssemble twice. This leads to system transactions' gas used is accumulated twice, later results in the mismatch between local and remote block's gas used calculation. We fix this issue by make a copy of block header before passing it to FinalizeAndAssemble. --- miner/worker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miner/worker.go b/miner/worker.go index 61402414a9..c86c1ef5e3 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -1035,7 +1035,7 @@ func (w *worker) commit(uncles []*types.Header, interval func(), update bool, st // Deep copy receipts here to avoid interaction between different tasks. receiptsCpy := copyReceipts(w.current.receipts) s := w.current.state.Copy() - block, receipts, err := w.engine.FinalizeAndAssemble(w.chain, w.current.header, s, w.current.txs, uncles, receiptsCpy) + block, receipts, err := w.engine.FinalizeAndAssemble(w.chain, types.CopyHeader(w.current.header), s, w.current.txs, uncles, receiptsCpy) if err != nil { return err } From 37306723521813b69bfe02118f83ac7273732258 Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Fri, 23 Sep 2022 11:38:40 +0700 Subject: [PATCH 32/52] [RON-250] fix: backward compatible with v1 snapshot (#128) * fix: load snapshot v1 * fix: store snapshot with the key consortium- * chore(snapshot): remove check condition at block 0 and fork * Choose the correct consortium version of ecrecover to be used on block header * Log slashing on finalize only, add some comments on snapshot Co-authored-by: Bui Quang Minh --- consensus/consortium/common/contract.go | 2 - consensus/consortium/v1/consortium.go | 6 +- consensus/consortium/v1/snapshot.go | 2 +- consensus/consortium/v2/consortium.go | 49 ++++++--------- consensus/consortium/v2/snapshot.go | 81 ++++++++++++++++++++----- 5 files changed, 90 insertions(+), 50 deletions(-) diff --git a/consensus/consortium/common/contract.go b/consensus/consortium/common/contract.go index f26b356a87..12aa6fd201 100644 --- a/consensus/consortium/common/contract.go +++ b/consensus/consortium/common/contract.go @@ -152,8 +152,6 @@ func (c *ContractIntegrator) SubmitBlockReward(opts *ApplyTransactOpts) error { } func (c *ContractIntegrator) Slash(opts *ApplyTransactOpts, spoiledValidator common.Address) error { - log.Warn("Slash validator", "number", opts.Header.Number.Uint64(), "coinbase", c.coinbase.Hex(), "spoiled", spoiledValidator.Hex()) - nonce := opts.State.GetNonce(c.coinbase) tx, err := c.slashIndicatorSC.Slash(getTransactionOpts(c.coinbase, nonce, c.chainId, c.signTxFn), spoiledValidator) if err != nil { diff --git a/consensus/consortium/v1/consortium.go b/consensus/consortium/v1/consortium.go index 41218b56a9..9f1dc92460 100644 --- a/consensus/consortium/v1/consortium.go +++ b/consensus/consortium/v1/consortium.go @@ -154,7 +154,7 @@ func (c *Consortium) SetGetFenixValidators(fn func() ([]common.Address, error)) // Author implements consensus.Engine, returning the Ethereum address recovered // from the signature in the header's extra-data section. func (c *Consortium) Author(header *types.Header) (common.Address, error) { - return ecrecover(header, c.signatures) + return Ecrecover(header, c.signatures) } // VerifyHeader checks whether a header conforms to the consensus rules. @@ -401,7 +401,7 @@ func (c *Consortium) verifySeal(chain consensus.ChainHeaderReader, header *types } // Resolve the authorization key and check against signers - signer, err := ecrecover(header, c.signatures) + signer, err := Ecrecover(header, c.signatures) if err != nil { return err } @@ -788,7 +788,7 @@ func (c *Consortium) initContract() error { } // ecrecover extracts the Ethereum account address from a signed header. -func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) { +func Ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) { // If the signature's already cached, return that hash := header.Hash() if address, known := sigcache.Get(hash); known { diff --git a/consensus/consortium/v1/snapshot.go b/consensus/consortium/v1/snapshot.go index a648285534..6d3de54390 100644 --- a/consensus/consortium/v1/snapshot.go +++ b/consensus/consortium/v1/snapshot.go @@ -135,7 +135,7 @@ func (s *Snapshot) apply(chain consensus.ChainHeaderReader, c *Consortium, heade } // Resolve the authorization key and check against signers - signer, err := ecrecover(header, s.sigcache) + signer, err := Ecrecover(header, s.sigcache) if err != nil { return nil, err } diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index f3a13a8015..bbe332e5b5 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -327,40 +327,28 @@ func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64, // If an on-disk checkpoint snapshot can be found, use that if number%c.config.Epoch == 0 { - if s, err := loadSnapshot(c.config, c.signatures, c.db, hash, c.ethAPI); err == nil { - log.Trace("Loaded snapshot from disk", "number", number, "hash", hash) - snap = s - break + var err error + + // In case the snapshot of hardfork - 1 is requested, we find the latest snapshot in the last + // checkpoint of v1. We need to use the correct load snapshot version to load the snapshot coming + // from v1. + if !c.chainConfig.IsConsortiumV2(common.Big0.SetUint64(number)) { + snap, err = loadSnapshotV1(c.config, c.signatures, c.db, hash, c.ethAPI, c.chainConfig) + } else { + snap, err = loadSnapshot(c.config, c.signatures, c.db, hash, c.ethAPI, c.chainConfig) } - } - - // If we're at the genesis, snapshot the initial state. - if number == 0 || c.chainConfig.IsOnConsortiumV2(big.NewInt(0).SetUint64(number+1)) { - checkpoint := chain.GetHeaderByNumber(number) - if checkpoint != nil { - // get checkpoint data - hash := checkpoint.Hash() - - validators, err := c.contract.GetValidators(checkpoint) - if err != nil { - return nil, err - } - snap = newSnapshot(c.config, c.signatures, number, hash, validators, c.ethAPI) - // get recents from v1 if number is end of v1 - if c.chainConfig.IsOnConsortiumV2(big.NewInt(0).SetUint64(number + 1)) { - recents := consortiumCommon.RemoveOutdatedRecents(c.v1.GetRecents(chain, number), number) + if err != nil { + log.Debug("Load snapshot failed", "number", number, "hash", hash.Hex()) + } - if recents != nil { - log.Info("adding previous recents to current snapshot", "number", number, "hash", hash.Hex(), "recents", recents) - snap.Recents = recents - } - } - // store snap to db - if err := snap.store(c.db); err != nil { - return nil, err + if err == nil { + log.Trace("Loaded snapshot from disk", "number", number, "hash", hash.Hex()) + if !c.chainConfig.IsConsortiumV2(common.Big0.SetUint64(snap.Number)) { + // Clean up the incorrect data in recent list + snap.Recents = consortiumCommon.RemoveOutdatedRecents(snap.Recents, number) + log.Info("Added previous recents to current snapshot", "number", number, "hash", hash.Hex(), "recents", snap.Recents) } - log.Info("Stored checkpoint snapshot to disk", "number", number, "hash", hash) break } } @@ -582,6 +570,7 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H } } if !signedRecently { + log.Info("Slash validator", "number", header.Number, "spoiled", spoiledVal) err = c.contract.Slash(transactOpts, spoiledVal) if err != nil { // it is possible that slash validator failed because of the slash channel is disabled. diff --git a/consensus/consortium/v2/snapshot.go b/consensus/consortium/v2/snapshot.go index 9c73fe1830..5d6b03810b 100644 --- a/consensus/consortium/v2/snapshot.go +++ b/consensus/consortium/v2/snapshot.go @@ -6,6 +6,7 @@ import ( "errors" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" + v1 "github.com/ethereum/go-ethereum/consensus/consortium/v1" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/internal/ethapi" @@ -16,9 +17,10 @@ import ( ) type Snapshot struct { - config *params.ConsortiumConfig // Consensus engine parameters to fine tune behavior - ethAPI *ethapi.PublicBlockChainAPI - sigCache *lru.ARCCache // Cache of recent block signatures to speed up ecrecover + chainConfig *params.ChainConfig + config *params.ConsortiumConfig // Consensus engine parameters to fine tune behavior + ethAPI *ethapi.PublicBlockChainAPI + sigCache *lru.ARCCache // Cache of recent block signatures to speed up ecrecover Number uint64 `json:"number"` // Block number where the snapshot was created Hash common.Hash `json:"hash"` // Block hash where the snapshot was created @@ -49,8 +51,47 @@ func newSnapshot(config *params.ConsortiumConfig, sigcache *lru.ARCCache, number return snap } -func loadSnapshot(config *params.ConsortiumConfig, sigcache *lru.ARCCache, db ethdb.Database, hash common.Hash, ethAPI *ethapi.PublicBlockChainAPI) (*Snapshot, error) { - blob, err := db.Get(append([]byte("consortium-v2-"), hash[:]...)) +func loadSnapshotV1( + config *params.ConsortiumConfig, + sigcache *lru.ARCCache, + db ethdb.Database, + hash common.Hash, + ethAPI *ethapi.PublicBlockChainAPI, + chainConfig *params.ChainConfig, +) (*Snapshot, error) { + + blob, err := db.Get(append([]byte("consortium-"), hash[:]...)) + if err != nil { + return nil, err + } + snap := new(v1.Snapshot) + if err := json.Unmarshal(blob, snap); err != nil { + return nil, err + } + + snapV2 := &Snapshot{ + chainConfig: chainConfig, + config: config, + ethAPI: ethAPI, + sigCache: sigcache, + Number: snap.Number, + Hash: snap.Hash, + Validators: snap.SignerSet, + Recents: snap.Recents, + } + + return snapV2, nil +} + +func loadSnapshot( + config *params.ConsortiumConfig, + sigcache *lru.ARCCache, + db ethdb.Database, + hash common.Hash, + ethAPI *ethapi.PublicBlockChainAPI, + chainConfig *params.ChainConfig, +) (*Snapshot, error) { + blob, err := db.Get(append([]byte("consortium-"), hash[:]...)) if err != nil { return nil, err } @@ -61,6 +102,7 @@ func loadSnapshot(config *params.ConsortiumConfig, sigcache *lru.ARCCache, db et snap.config = config snap.sigCache = sigcache snap.ethAPI = ethAPI + snap.chainConfig = chainConfig return snap, nil } @@ -70,18 +112,19 @@ func (s *Snapshot) store(db ethdb.Database) error { if err != nil { return err } - return db.Put(append([]byte("consortium-v2-"), s.Hash[:]...), blob) + return db.Put(append([]byte("consortium-"), s.Hash[:]...), blob) } func (s *Snapshot) copy() *Snapshot { cpy := &Snapshot{ - config: s.config, - ethAPI: s.ethAPI, - sigCache: s.sigCache, - Number: s.Number, - Hash: s.Hash, - Validators: make(map[common.Address]struct{}), - Recents: make(map[uint64]common.Address), + chainConfig: s.chainConfig, + config: s.config, + ethAPI: s.ethAPI, + sigCache: s.sigCache, + Number: s.Number, + Hash: s.Hash, + Validators: make(map[common.Address]struct{}), + Recents: make(map[uint64]common.Address), } for v := range s.Validators { @@ -123,7 +166,17 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea delete(snap.Recents, number-limit) } // Resolve the authorization key and check against signers - validator, err := ecrecover(header, s.sigCache, chainId) + var ( + validator common.Address + err error + ) + // If the headers come from v1 the block hash function does not include chainId, + // we need to use the correct ecrecover function the get the correct signer + if !snap.chainConfig.IsConsortiumV2(header.Number) { + validator, err = v1.Ecrecover(header, s.sigCache) + } else { + validator, err = ecrecover(header, s.sigCache, chainId) + } if err != nil { return nil, err } From 41018554da3bd89298afa9858ca28f7095c2a58b Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Fri, 23 Sep 2022 13:22:13 +0700 Subject: [PATCH 33/52] [RON-251] fix: unknown ancestor (#129) * fix: unknown ancestor * chore: remove unused log * fix: remove line on comment * fix: remove unnecessary comment --- consensus/consortium/common/constants.go | 2 +- consensus/consortium/common/utils.go | 1 + consensus/consortium/v1/consortium.go | 2 +- consensus/consortium/v2/consortium.go | 19 +++++++++++++++---- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/consensus/consortium/common/constants.go b/consensus/consortium/common/constants.go index 7f68b57bd8..5cf4ed5afc 100644 --- a/consensus/consortium/common/constants.go +++ b/consensus/consortium/common/constants.go @@ -48,7 +48,7 @@ var ( // ErrRecentlySigned is returned if a header is signed by an authorized entity // that already signed a header recently, thus is temporarily not allowed to. - ErrRecentlySigned = errors.New("recently signed") + ErrRecentlySigned = errors.New("signed recently, must wait for others") // ErrWrongDifficulty is returned if the difficulty of a block doesn't match the // turn of the signer. diff --git a/consensus/consortium/common/utils.go b/consensus/consortium/common/utils.go index fa41157898..a65acf7b6f 100644 --- a/consensus/consortium/common/utils.go +++ b/consensus/consortium/common/utils.go @@ -41,6 +41,7 @@ func SignerInList(signer common.Address, validators []common.Address) bool { return false } +// RemoveOutdatedRecents removes outdated recents list func RemoveOutdatedRecents(recents map[uint64]common.Address, currentBlock uint64) map[uint64]common.Address { var blocks []uint64 for n, _ := range recents { diff --git a/consensus/consortium/v1/consortium.go b/consensus/consortium/v1/consortium.go index 9f1dc92460..7a1233be6d 100644 --- a/consensus/consortium/v1/consortium.go +++ b/consensus/consortium/v1/consortium.go @@ -642,7 +642,7 @@ func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, if recent == signer { // Signer is among recents, only wait if the current block doesn't shift it out if limit := uint64(len(validators)/2 + 1); seen > number-limit { - return errors.New("signed recently, must wait for others") + return consortiumCommon.ErrRecentlySigned } } } diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index bbe332e5b5..f901a3c220 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -316,6 +316,9 @@ func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64, var ( headers []*types.Header snap *Snapshot + // @linh: We must copy parents before going to the loop because parents are modified. + // If not, the FindAncientHeader function can not find its block ancestor + cpyParents = parents ) for snap == nil { @@ -329,7 +332,7 @@ func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64, if number%c.config.Epoch == 0 { var err error - // In case the snapshot of hardfork - 1 is requested, we find the latest snapshot in the last + // @linh: In case the snapshot of hardfork - 1 is requested, we find the latest snapshot in the last // checkpoint of v1. We need to use the correct load snapshot version to load the snapshot coming // from v1. if !c.chainConfig.IsConsortiumV2(common.Big0.SetUint64(number)) { @@ -345,7 +348,14 @@ func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64, if err == nil { log.Trace("Loaded snapshot from disk", "number", number, "hash", hash.Hex()) if !c.chainConfig.IsConsortiumV2(common.Big0.SetUint64(snap.Number)) { - // Clean up the incorrect data in recent list + // @linh: In version 1, the snapshot is not used correctly, so we must clean up incorrect data in + // the recent list before going to version 2 + // + // Example: The current block is 1000, and the recents list is + // [2: address1, 3: address2, ...,998: addressN - 1,999: addressN] + // So we need to remove these elements are not continuously + // So the final result must be + // [998: addressN - 1,999: addressN] snap.Recents = consortiumCommon.RemoveOutdatedRecents(snap.Recents, number) log.Info("Added previous recents to current snapshot", "number", number, "hash", hash.Hex(), "recents", snap.Recents) } @@ -354,6 +364,7 @@ func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64, } // No snapshot for this header, gather the header and move backward + // NOTE: We are modifying parents in here var header *types.Header if len(parents) > 0 { // If we have explicit parents, pick from there (enforced) @@ -383,7 +394,7 @@ func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64, headers[i], headers[len(headers)-1-i] = headers[len(headers)-1-i], headers[i] } - snap, err := snap.apply(headers, chain, parents, c.chainConfig.ChainID) + snap, err := snap.apply(headers, chain, cpyParents, c.chainConfig.ChainID) if err != nil { return nil, err } @@ -737,7 +748,7 @@ func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, if recent == val { // Signer is among recents, only wait if the current block doesn't shift it out if limit := uint64(len(snap.Validators)/2 + 1); number < limit || seen > number-limit { - return errors.New("signed recently, must wait for others") + return consortiumCommon.ErrRecentlySigned } } } From 6f99ab1fe8af5dcd9b946fab3828bc21614c7113 Mon Sep 17 00:00:00 2001 From: minh-bq <97180373+minh-bq@users.noreply.github.com> Date: Fri, 23 Sep 2022 13:25:23 +0700 Subject: [PATCH 34/52] Remove unused variables and functions (#130) * Remove unused variables and functions * Remove deadcode when checking system transactions --- consensus/consensus.go | 6 +- consensus/consortium/common/contract.go | 8 +-- consensus/consortium/main.go | 19 +---- consensus/consortium/v2/consortium.go | 77 ++------------------- consensus/consortium/v2/consortiumv2fork.go | 6 +- consensus/consortium/v2/snapshot.go | 47 +------------ core/state_processor.go | 7 -- 7 files changed, 21 insertions(+), 149 deletions(-) diff --git a/consensus/consensus.go b/consensus/consensus.go index 76bf0b517b..fe5a8e273d 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -18,10 +18,11 @@ package consensus import ( - "github.com/ethereum/go-ethereum/ethdb" "math/big" "time" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -146,7 +147,4 @@ type PoSA interface { IsSystemTransaction(tx *types.Transaction, header *types.Header) (bool, error) IsSystemContract(to *common.Address) bool - EnoughDistance(chain ChainReader, header *types.Header) bool - IsLocalBlock(header *types.Header) bool - AllowLightProcess(chain ChainReader, currentHeader *types.Header) bool } diff --git a/consensus/consortium/common/contract.go b/consensus/consortium/common/contract.go index 12aa6fd201..51b691ea75 100644 --- a/consensus/consortium/common/contract.go +++ b/consensus/consortium/common/contract.go @@ -6,6 +6,8 @@ import ( "encoding/hex" "errors" "fmt" + "math/big" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -13,8 +15,8 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/consortium/generated_contracts/ronin_validator_set" - "github.com/ethereum/go-ethereum/consensus/consortium/generated_contracts/slash_indicator" + roninValidatorSet "github.com/ethereum/go-ethereum/consensus/consortium/generated_contracts/ronin_validator_set" + slashIndicator "github.com/ethereum/go-ethereum/consensus/consortium/generated_contracts/slash_indicator" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -23,7 +25,6 @@ import ( "github.com/ethereum/go-ethereum/log" chainParams "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" - "math/big" ) var errMethodUnimplemented = errors.New("method is unimplemented") @@ -54,7 +55,6 @@ type ContractIntegrator struct { slashIndicatorSC *slashIndicator.SlashIndicator signTxFn SignerTxFn coinbase common.Address - config *chainParams.ChainConfig } func NewContractIntegrator(config *chainParams.ChainConfig, backend bind.ContractBackend, signTxFn SignerTxFn, coinbase common.Address) (*ContractIntegrator, error) { diff --git a/consensus/consortium/main.go b/consensus/consortium/main.go index 08f25814cd..e1d8c5b0a0 100644 --- a/consensus/consortium/main.go +++ b/consensus/consortium/main.go @@ -1,6 +1,9 @@ package consortium import ( + "math/big" + "time" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" consortiumCommon "github.com/ethereum/go-ethereum/consensus/consortium/common" @@ -12,8 +15,6 @@ import ( "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" - "math/big" - "time" ) type Consortium struct { @@ -36,8 +37,6 @@ func New(chainConfig *params.ChainConfig, db ethdb.Database, ee *ethapi.PublicBl } } -// Author since v1 and v2 are implemented the same logic, so we don't need to check whether the current block is version 1 -// or version 2 func (c *Consortium) Author(header *types.Header) (common.Address, error) { if c.chainConfig.IsConsortiumV2(header.Number) { return c.v2.Author(header) @@ -185,15 +184,3 @@ func (c *Consortium) IsSystemTransaction(tx *types.Transaction, header *types.He func (c *Consortium) IsSystemContract(to *common.Address) bool { return c.v2.IsSystemContract(to) } - -func (c *Consortium) EnoughDistance(chain consensus.ChainReader, header *types.Header) bool { - return c.v2.EnoughDistance(chain, header) -} - -func (c *Consortium) IsLocalBlock(header *types.Header) bool { - return c.v2.IsLocalBlock(header) -} - -func (c *Consortium) AllowLightProcess(chain consensus.ChainReader, currentHeader *types.Header) bool { - return c.v2.AllowLightProcess(chain, currentHeader) -} diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index f901a3c220..2c317ec438 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -4,6 +4,13 @@ import ( "bytes" "errors" "fmt" + "io" + "math/big" + "math/rand" + "sort" + "sync" + "time" + "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" @@ -21,20 +28,12 @@ import ( "github.com/ethereum/go-ethereum/trie" lru "github.com/hashicorp/golang-lru" "golang.org/x/crypto/sha3" - "io" - "math/big" - "math/rand" - "sort" - "sync" - "time" ) const ( inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory inmemorySignatures = 4096 // Number of recent block signatures to keep in memory - checkpointInterval = 1024 // Number of blocks after which to save the snapshot to the database - extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal @@ -68,9 +67,6 @@ var ( // that already signed a header recently, thus is temporarily not allowed to. errRecentlySigned = errors.New("recently signed") - // errMissingValidators is returned if you can not get list of validators. - errMissingValidators = errors.New("missing validators") - // errCoinBaseMisMatch is returned if a header's coinbase do not match with signature errCoinBaseMisMatch = errors.New("coinbase do not match with signature") @@ -96,7 +92,6 @@ type Consortium struct { lock sync.RWMutex // Protects the signer fields ethAPI *ethapi.PublicBlockChainAPI - statedb *state.StateDB contract *consortiumCommon.ContractIntegrator fakeDiff bool @@ -155,29 +150,6 @@ func (c *Consortium) IsSystemContract(to *common.Address) bool { return c.chainConfig.ConsortiumV2Contracts.IsSystemContract(*to) } -func (c *Consortium) EnoughDistance(chain consensus.ChainReader, header *types.Header) bool { - snap, err := c.snapshot(chain, header.Number.Uint64()-1, header.ParentHash, nil) - if err != nil { - return true - } - return snap.enoughDistance(c.val, header) -} - -func (c *Consortium) IsLocalBlock(header *types.Header) bool { - return c.val == header.Coinbase -} - -func (c *Consortium) AllowLightProcess(chain consensus.ChainReader, currentHeader *types.Header) bool { - snap, err := c.snapshot(chain, currentHeader.Number.Uint64()-1, currentHeader.ParentHash, nil) - if err != nil { - return true - } - - idx := snap.indexOfVal(c.val) - // validator is not allowed to diff sync - return idx < 0 -} - func (c *Consortium) Author(header *types.Header) (common.Address, error) { return header.Coinbase, nil } @@ -267,19 +239,6 @@ func (c *Consortium) verifyCascadingFields(chain consensus.ChainHeaderReader, he return consensus.ErrUnknownAncestor } - // Verify list validators - // Note: Verify it in Finalize - //validators, err := c.getCurrentValidators(header.Hash(), header.Number) - //if err != nil { - // return errMissingValidators - //} - //checkpointValidators := c.getValidatorsFromHeader(header) - //validValidators := consortiumCommon.CompareSignersLists(validators, checkpointValidators) - //if !validValidators { - // log.Error("signers lists are different in checkpoint header and snapshot", "number", number, "validatorsHeader", checkpointValidators, "signers", validators) - // return consortiumCommon.ErrInvalidCheckpointSigners - //} - // Verify that the gas limit is <= 2^63-1 capacity := uint64(0x7fffffffffffffff) if header.GasLimit > capacity { @@ -290,16 +249,6 @@ func (c *Consortium) verifyCascadingFields(chain consensus.ChainHeaderReader, he return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) } - // Verify that the gas limit remains within allowed bounds - //diff := int64(parent.GasLimit) - int64(header.GasLimit) - //if diff < 0 { - // diff *= -1 - //} - //limit := parent.GasLimit / params.ConsortiumGasLimitBoundDivisor - // - //if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit { - // return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit) - //} if err := misc.VerifyGaslimit(parent.GasLimit, header.GasLimit); err != nil { return err } @@ -821,11 +770,6 @@ func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int { return new(big.Int).Set(diffNoTurn) } -func (c *Consortium) getValidatorsFromHeader(header *types.Header) []common.Address { - extraSuffix := len(header.Extra) - consortiumCommon.ExtraSeal - return consortiumCommon.ExtractAddressFromBytes(header.Extra[extraVanity:extraSuffix]) -} - func (c *Consortium) initContract() error { contract, err := consortiumCommon.NewContractIntegrator(c.chainConfig, consortiumCommon.NewConsortiumBackend(c.ethAPI), c.signTxFn, c.val) if err != nil { @@ -836,13 +780,6 @@ func (c *Consortium) initContract() error { return nil } -// Check if it is the turn of the signer from the last checkpoint -func (c *Consortium) signerInTurn(signer common.Address, number uint64, validators []common.Address) bool { - lastCheckpoint := number / c.config.Epoch * c.config.Epoch - index := (number - lastCheckpoint) % uint64(len(validators)) - return validators[index] == signer -} - // ecrecover extracts the Ethereum account address from a signed header. func ecrecover(header *types.Header, sigcache *lru.ARCCache, chainId *big.Int) (common.Address, error) { // If the signature's already cached, return that diff --git a/consensus/consortium/v2/consortiumv2fork.go b/consensus/consortium/v2/consortiumv2fork.go index cfb771b43b..37d144c8f8 100644 --- a/consensus/consortium/v2/consortiumv2fork.go +++ b/consensus/consortium/v2/consortiumv2fork.go @@ -1,9 +1,10 @@ package v2 import ( - "github.com/ethereum/go-ethereum/core/types" "math/rand" "time" + + "github.com/ethereum/go-ethereum/core/types" ) const ( @@ -26,8 +27,5 @@ func (c *Consortium) delayForConsortiumV2Fork(snap *Snapshot, header *types.Head func (c *Consortium) blockTimeForConsortiumV2Fork(snap *Snapshot, header, parent *types.Header) uint64 { blockTime := parent.Time + c.config.Period - //if c.chainConfig.IsConsortiumV2(header.Number) { - // blockTime = blockTime + backOffTime(snap, c.val) - //} return blockTime } diff --git a/consensus/consortium/v2/snapshot.go b/consensus/consortium/v2/snapshot.go index 5d6b03810b..26d5c52cff 100644 --- a/consensus/consortium/v2/snapshot.go +++ b/consensus/consortium/v2/snapshot.go @@ -4,6 +4,9 @@ import ( "bytes" "encoding/json" "errors" + "math/big" + "sort" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" v1 "github.com/ethereum/go-ethereum/consensus/consortium/v1" @@ -12,8 +15,6 @@ import ( "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/params" lru "github.com/hashicorp/golang-lru" - "math/big" - "sort" ) type Snapshot struct { @@ -213,8 +214,6 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea delete(snap.Recents, number-uint64(newLimit)-uint64(i)) } } - oldLimit = len(snap.Validators) - newLimit = len(newVals) snap.Validators = newVals } } @@ -233,36 +232,6 @@ func (s *Snapshot) validators() []common.Address { return validators } -func (s *Snapshot) enoughDistance(validator common.Address, header *types.Header) bool { - idx := s.indexOfVal(validator) - if idx < 0 { - return true - } - validatorNum := int64(len(s.validators())) - if validatorNum == 1 { - return true - } - if validator == header.Coinbase { - return false - } - offset := (int64(s.Number) + 1) % validatorNum - if int64(idx) >= offset { - return int64(idx)-offset >= validatorNum-2 - } else { - return validatorNum+int64(idx)-offset >= validatorNum-2 - } -} - -func (s *Snapshot) indexOfVal(validator common.Address) int { - validators := s.validators() - for idx, val := range validators { - if val == validator { - return idx - } - } - return -1 -} - // inturn returns if a validator at a given block height is in-turn or not. func (s *Snapshot) inturn(validator common.Address) bool { validators := s.validators() @@ -316,13 +285,3 @@ func FindAncientHeader(header *types.Header, ite uint64, chain consensus.ChainHe } return ancient } - -//func (s *Snapshot) isMajorityFork(forkHash string) bool { -// ally := 0 -// for _, h := range s.RecentForkHashes { -// if h == forkHash { -// ally++ -// } -// } -// return ally > len(s.RecentForkHashes)/2 -//} diff --git a/core/state_processor.go b/core/state_processor.go index 2b035e5c59..49b8c31cd0 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -96,13 +96,6 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg } } - hasConsortiumV2Contracts := p.config.ConsortiumV2Contracts != nil - isConsortiumV2 := p.config.IsOnConsortiumV2(big.NewInt(int64(block.NumberU64() + 1))) - if hasConsortiumV2Contracts && isConsortiumV2 && tx.To() != nil && p.config.ConsortiumV2Contracts.IsSystemContract(*tx.To()) { - systemTxs = append(systemTxs, tx) - continue - } - // set current transaction in block context to each transaction vmenv.Context.CurrentTransaction = tx // reset counter to start counting opcodes in new transaction From 3f1c3d69c286cec593087e8a9306c9562303d31a Mon Sep 17 00:00:00 2001 From: minh-bq <97180373+minh-bq@users.noreply.github.com> Date: Fri, 23 Sep 2022 13:25:48 +0700 Subject: [PATCH 35/52] Call GetValidators on context of specific block instead of latest block (#131) --- consensus/consortium/common/contract.go | 7 +++++-- consensus/consortium/v2/consortium.go | 8 ++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/consensus/consortium/common/contract.go b/consensus/consortium/common/contract.go index 51b691ea75..94d0d5afc4 100644 --- a/consensus/consortium/common/contract.go +++ b/consensus/consortium/common/contract.go @@ -77,8 +77,11 @@ func NewContractIntegrator(config *chainParams.ChainConfig, backend bind.Contrac }, nil } -func (c *ContractIntegrator) GetValidators(header *types.Header) ([]common.Address, error) { - addresses, err := c.roninValidatorSetSC.GetValidators(nil) +func (c *ContractIntegrator) GetValidators(blockNumber *big.Int) ([]common.Address, error) { + callOpts := bind.CallOpts{ + BlockNumber: blockNumber, + } + addresses, err := c.roninValidatorSetSC.GetValidators(&callOpts) if err != nil { return nil, err } diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index 2c317ec438..b8ebdebe21 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -443,7 +443,9 @@ func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.He header.Extra = header.Extra[:extraVanity] if number%c.config.Epoch == 0 || c.chainConfig.IsOnConsortiumV2(big.NewInt(int64(number))) { - newValidators, err := c.contract.GetValidators(header) + // This block is not inserted, the transactions in this block are not applied, so we need + // the call GetValidators at the context of previous block + newValidators, err := c.contract.GetValidators(new(big.Int).Sub(header.Number, common.Big1)) if err != nil { return err } @@ -503,7 +505,9 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H // If the block is a epoch end block, verify the validator list // The verification can only be done when the state is ready, it can't be done in VerifyHeader. if header.Number.Uint64()%c.config.Epoch == 0 { - newValidators, err := c.contract.GetValidators(header) + // The GetValidators in Prepare is called on the context of previous block so here it must + // be called on context of previous block too + newValidators, err := c.contract.GetValidators(new(big.Int).Sub(header.Number, common.Big1)) if err != nil { return err } From 9fc303aa7d3a8874df80cf27163d65534e28d332 Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Thu, 29 Sep 2022 11:12:56 +0700 Subject: [PATCH 36/52] feat: Implement log precompiled contract (#134) * feat: Implement log precompiled contract * chore: minify consortiumLog's abi * chore: Add consortium precompiled contracts to list * chore: only allow log in debug mode (--vmdebug or `DEBUG` env is set to "true") * chore: Remove redundant function which get method from abi and input --- cmd/utils/flags.go | 2 ++ core/vm/contracts.go | 59 ++++++++++++++++++++++++++++++++++++--- core/vm/contracts_test.go | 30 ++++++++++++++++++++ core/vm/evm.go | 6 ++++ core/vm/evm_test.go | 5 ++-- 5 files changed, 96 insertions(+), 6 deletions(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index f760254b23..532df59056 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1659,6 +1659,8 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { if ctx.GlobalIsSet(VMEnableDebugFlag.Name) { // TODO(fjl): force-enable this in --dev mode cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name) + // set debug environment to true + os.Setenv("DEBUG", "true") } if ctx.GlobalIsSet(RPCGlobalGasCapFlag.Name) { diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 82a778bc36..5e4b44e450 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -20,7 +20,11 @@ import ( "crypto/sha256" "encoding/binary" "errors" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/log" "math/big" + "os" + "strings" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" @@ -106,11 +110,16 @@ var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{18}): &bls12381MapG2{}, } +var PrecompiledContractsConsortium = map[common.Address]PrecompiledContract{ + common.BytesToAddress([]byte{101}): &consortiumLog{}, +} + var ( - PrecompiledAddressesBerlin []common.Address - PrecompiledAddressesIstanbul []common.Address - PrecompiledAddressesByzantium []common.Address - PrecompiledAddressesHomestead []common.Address + PrecompiledAddressesBerlin []common.Address + PrecompiledAddressesIstanbul []common.Address + PrecompiledAddressesByzantium []common.Address + PrecompiledAddressesHomestead []common.Address + PrecompiledAddressesConsortium []common.Address ) func init() { @@ -126,6 +135,9 @@ func init() { for k := range PrecompiledContractsBerlin { PrecompiledAddressesBerlin = append(PrecompiledAddressesBerlin, k) } + for k := range PrecompiledContractsConsortium { + PrecompiledAddressesConsortium = append(PrecompiledAddressesConsortium, k) + } } // ActivePrecompiles returns the precompiles enabled with the current configuration. @@ -1057,3 +1069,42 @@ func (c *bls12381MapG2) Run(input []byte) ([]byte, error) { // Encode the G2 point to 256 bytes return g.EncodePoint(r), nil } + +var consortiumLogAbi = `[{"inputs":[{"internalType":"string","name":"message","type":"string"}],"name":"log","outputs":[],"stateMutability":"nonpayable","type":"function"}]` + +type consortiumLog struct{} + +func (c *consortiumLog) RequiredGas(input []byte) uint64 { + return 0 +} + +func (c *consortiumLog) Run(input []byte) ([]byte, error) { + if os.Getenv("DEBUG") != "true" { + return input, nil + } + var ( + pAbi abi.ABI + err error + method *abi.Method + args []interface{} + ) + if pAbi, err = abi.JSON(strings.NewReader(consortiumLogAbi)); err != nil { + return nil, err + } + if method, err = pAbi.MethodById(input); err != nil { + return nil, err + } + switch method.Name { + case "log": + if args, err = method.Inputs.Unpack(input[4:]); err != nil { + return nil, err + } + if len(args) == 0 { + return input, nil + } + if _, ok := args[0].(string); ok { + log.Info("[consortiumLog] log message from smart contract", "message", args[0].(string)) + } + } + return input, nil +} diff --git a/core/vm/contracts_test.go b/core/vm/contracts_test.go index 30d9b49f71..f70f78fd35 100644 --- a/core/vm/contracts_test.go +++ b/core/vm/contracts_test.go @@ -20,7 +20,11 @@ import ( "bytes" "encoding/json" "fmt" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/log" "io/ioutil" + "os" + "strings" "testing" "time" @@ -65,6 +69,7 @@ var allPrecompiles = map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{16}): &bls12381Pairing{}, common.BytesToAddress([]byte{17}): &bls12381MapG1{}, common.BytesToAddress([]byte{18}): &bls12381MapG2{}, + common.BytesToAddress([]byte{101}): &consortiumLog{}, } // EIP-152 test vectors @@ -311,6 +316,31 @@ func TestPrecompiledBLS12381G2MultiExp(t *testing.T) { testJson("blsG2MultiExp", func TestPrecompiledBLS12381Pairing(t *testing.T) { testJson("blsPairing", "10", t) } func TestPrecompiledBLS12381MapG1(t *testing.T) { testJson("blsMapG1", "11", t) } func TestPrecompiledBLS12381MapG2(t *testing.T) { testJson("blsMapG2", "12", t) } +func TestPrecompiledConsortiumLog(t *testing.T) { + glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) + glogger.Verbosity(log.LvlInfo) + log.Root().SetHandler(glogger) + var ( + pAbi abi.ABI + err error + ) + if pAbi, err = abi.JSON(strings.NewReader(consortiumLogAbi)); err != nil { + t.Fatal(err) + } + data, err := pAbi.Pack("log", "hello world") + if err != nil { + panic(err) + } + test := precompiledTest{ + Name: "test consortium log", + Input: common.Bytes2Hex(data), + Expected: common.Bytes2Hex(data), + Gas: 0, + NoBenchmark: true, + } + // 0x65 is hex of 101 + testPrecompiled("65", test, t) +} func BenchmarkPrecompiledBLS12381G1Add(b *testing.B) { benchJson("blsG1Add", "0a", b) } func BenchmarkPrecompiledBLS12381G1Mul(b *testing.B) { benchJson("blsG1Mul", "0b", b) } diff --git a/core/vm/evm.go b/core/vm/evm.go index 3acbac979e..082cef5526 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -72,6 +72,12 @@ func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { default: precompiles = PrecompiledContractsHomestead } + + // add consortium precompiled contracts to list + for address, contract := range PrecompiledContractsConsortium { + precompiles[address] = contract + } + p, ok := precompiles[addr] return p, ok } diff --git a/core/vm/evm_test.go b/core/vm/evm_test.go index 4481373905..e6756e637b 100644 --- a/core/vm/evm_test.go +++ b/core/vm/evm_test.go @@ -12,7 +12,8 @@ type TestOpEvent struct { feed *event.Feed } -func (tx *TestOpEvent) Publish(stateDB StateDB, hash common.Hash, from, to common.Address, value *big.Int, input []byte, err error) error { +func (tx *TestOpEvent) Publish(opcode OpCode, order uint64, stateDB StateDB, blockHeight uint64, + blockHash common.Hash, blockTime uint64, hash common.Hash, from, to common.Address, value *big.Int, input []byte, err error) error { tx.feed.Send(true) return nil } @@ -42,7 +43,7 @@ func TestPublishEvents(t *testing.T) { } evm := &EVM{Context: ctx} - evm.PublishEvent(CALL, common.Address{}, common.Address{}, big.NewInt(0), []byte(""), nil) + evm.PublishEvent(CALL, 1, common.Address{}, common.Address{}, big.NewInt(0), []byte(""), nil) select { case rs = <-ch: if !rs { From b47da9b08557344ddb7af5b69442f26ccd0474db Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Thu, 29 Sep 2022 11:56:18 +0700 Subject: [PATCH 37/52] fix: update smart contract ABI (#132) --- .../ronin_validator_set.go | 3335 ++++++++++++++++- .../slash_indicator/slash_indicator.go | 1387 ++++++- 2 files changed, 4415 insertions(+), 307 deletions(-) diff --git a/consensus/consortium/generated_contracts/ronin_validator_set/ronin_validator_set.go b/consensus/consortium/generated_contracts/ronin_validator_set/ronin_validator_set.go index 57f2c8f7ff..ec524310a6 100644 --- a/consensus/consortium/generated_contracts/ronin_validator_set/ronin_validator_set.go +++ b/consensus/consortium/generated_contracts/ronin_validator_set/ronin_validator_set.go @@ -28,10 +28,19 @@ var ( _ = event.NewSubscription ) +// ICandidateManagerValidatorCandidate is an auto generated low-level Go binding around an user-defined struct. +type ICandidateManagerValidatorCandidate struct { + Admin common.Address + ConsensusAddr common.Address + TreasuryAddr common.Address + CommissionRate *big.Int + ExtraData []byte +} + // RoninValidatorSetMetaData contains all meta data concerning the RoninValidatorSet contract. var RoninValidatorSetMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"epochEndingAt\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"epochOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastUpdatedBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getValidators\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"_validatorList\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governanceAdminContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__governanceAdminContract\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__slashIndicatorContract\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__stakingContract\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"__maxValidatorNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"__numberOfBlocksInEpoch\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"__numberOfEpochsInPeriod\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_slashFelonyAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_slashDoubleSignAmount\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_addrList\",\"type\":\"address[]\"}],\"name\":\"jailed\",\"outputs\":[{\"internalType\":\"bool[]\",\"name\":\"_result\",\"type\":\"bool[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_addrList\",\"type\":\"address[]\"},{\"internalType\":\"uint256\",\"name\":\"_period\",\"type\":\"uint256\"}],\"name\":\"noPendingReward\",\"outputs\":[{\"internalType\":\"bool[]\",\"name\":\"_result\",\"type\":\"bool[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"numberOfBlocksInEpoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_numberOfBlocks\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"numberOfEpochsInPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_numberOfEpochs\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"periodEndingAt\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"periodOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validatorAddr\",\"type\":\"address\"}],\"name\":\"slashDoubleSign\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"slashDoubleSignAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validatorAddr\",\"type\":\"address\"}],\"name\":\"slashFelony\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"slashFelonyAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"slashIndicatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validatorAddr\",\"type\":\"address\"}],\"name\":\"slashMisdemeanor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakingContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"submitBlockReward\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"validatorCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"wrapUpEpoch\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", - Bin: "0x60806040523480156200001157600080fd5b50620000226200002860201b60201c565b620001d3565b600060019054906101000a900460ff16156200007b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000729062000176565b60405180910390fd5b60ff801660008054906101000a900460ff1660ff161015620000ed5760ff6000806101000a81548160ff021916908360ff1602179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249860ff604051620000e49190620001b6565b60405180910390a15b565b600082825260208201905092915050565b7f496e697469616c697a61626c653a20636f6e747261637420697320696e69746960008201527f616c697a696e6700000000000000000000000000000000000000000000000000602082015250565b60006200015e602783620000ef565b91506200016b8262000100565b604082019050919050565b6000602082019050818103600083015262000191816200014f565b9050919050565b600060ff82169050919050565b620001b08162000198565b82525050565b6000602082019050620001cd6000830184620001a5565b92915050565b61321280620001e36000396000f3fe6080604052600436106101355760003560e01c806372e46810116100ab578063b7ab4db51161006f578063b7ab4db5146103fc578063df8fa43014610427578063dfe484cb14610450578063ea82f7841461047b578063ee99205c146104a6578063f8549af9146104d157610135565b806372e46810146103245780637593ff711461032e5780637ae46af31461036b57806387c891bd14610394578063a3d545f5146103bf57610135565b806352091f17116100fd57806352091f17146102335780635a08482d1461023d5780636aa1c2ef146102685780636d14c4e51461029357806371e594b3146102be578063722d298f146102fb57610135565b80630f43a6771461013a57806325a6b529146101655780633dc56e09146101a25780634454af9d146101cb5780635186dc7e14610208575b600080fd5b34801561014657600080fd5b5061014f61050e565b60405161015c91906121df565b60405180910390f35b34801561017157600080fd5b5061018c6004803603810190610187919061223a565b610514565b6040516101999190612282565b60405180910390f35b3480156101ae57600080fd5b506101c960048036038101906101c491906122fb565b61054b565b005b3480156101d757600080fd5b506101f260048036038101906101ed9190612481565b610766565b6040516101ff9190612588565b60405180910390f35b34801561021457600080fd5b5061021d6107d5565b60405161022a91906121df565b60405180910390f35b61023b6107df565b005b34801561024957600080fd5b50610252610b03565b60405161025f91906125b9565b60405180910390f35b34801561027457600080fd5b5061027d610b2d565b60405161028a91906121df565b60405180910390f35b34801561029f57600080fd5b506102a8610b37565b6040516102b591906121df565b60405180910390f35b3480156102ca57600080fd5b506102e560048036038101906102e091906125d4565b610b3d565b6040516102f29190612588565b60405180910390f35b34801561030757600080fd5b50610322600480360381019061031d91906122fb565b610c02565b005b61032c610dce565b005b34801561033a57600080fd5b506103556004803603810190610350919061223a565b61132b565b6040516103629190612282565b60405180910390f35b34801561037757600080fd5b50610392600480360381019061038d91906122fb565b611352565b005b3480156103a057600080fd5b506103a96114e3565b6040516103b691906121df565b60405180910390f35b3480156103cb57600080fd5b506103e660048036038101906103e1919061223a565b6114ed565b6040516103f391906121df565b60405180910390f35b34801561040857600080fd5b50610411611510565b60405161041e91906126ee565b60405180910390f35b34801561043357600080fd5b5061044e60048036038101906104499190612710565b611603565b005b34801561045c57600080fd5b50610465611827565b60405161047291906121df565b60405180910390f35b34801561048757600080fd5b5061049061182d565b60405161049d91906125b9565b60405180910390f35b3480156104b257600080fd5b506104bb611856565b6040516104c891906125b9565b60405180910390f35b3480156104dd57600080fd5b506104f860048036038101906104f3919061223a565b611880565b60405161050591906121df565b60405180910390f35b60035481565b60008060085460075461052791906127f5565b9050600181610536919061284f565b818461054291906128b2565b14915050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146105db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d29061298c565b60405180910390fd5b6001600a60006105ea43611880565b815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506000600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506000600d60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a5885f1d826040518263ffffffff1660e01b815260040161073191906125b9565b600060405180830381600087803b15801561074b57600080fd5b505af115801561075f573d6000803e3d6000fd5b5050505050565b606060005b82518110156107cf5761079783828151811061078a576107896129ac565b5b60200260200101516118b0565b8282815181106107aa576107a96129ac565b5b60200260200101901515908115158152505080806107c7906129db565b91505061076b565b50919050565b6000600854905090565b4173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461084d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161084490612a95565b60405180910390fd5b60003490506000339050610860816118fc565b61086b575050610b01565b610874816118b0565b806108e15750600a600061088743611880565b815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b156108ed575050610b01565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008173ffffffffffffffffffffffffffffffffffffffff16635a783656846040518263ffffffff1660e01b815260040161094f91906125b9565b602060405180830381865afa15801561096c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109909190612aca565b9050600061271085836109a391906127f5565b6109ad9190612af7565b9050600081866109bd919061284f565b905081600c60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610a0e9190612b28565b9250508190555080600d60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610a649190612b28565b92505081905550600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b863d71086836040518363ffffffff1660e01b8152600401610ac8929190612b5c565b600060405180830381600087803b158015610ae257600080fd5b505af1158015610af6573d6000803e3d6000fd5b505050505050505050505b565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600754905090565b600f5481565b606060005b8351811015610bfb57600a60008481526020019081526020016000206000858381518110610b7357610b726129ac565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16828281518110610bd657610bd56129ac565b5b6020026020010190151590811515815250508080610bf3906129db565b915050610b42565b5092915050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c92576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c899061298c565b60405180910390fd5b610c9b8161054b565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c905bb3582600e546040518363ffffffff1660e01b8152600401610cfa929190612b5c565b600060405180830381600087803b158015610d1457600080fd5b505af1158015610d28573d6000803e3d6000fd5b50505050600061e10043610d3c9190612b28565b9050610d87600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482611952565b600b60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505050565b4173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610e3c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e3390612a95565b60405180910390fd5b610e454361132b565b610e84576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7b90612bf7565b60405180910390fd5b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000806000610eb943611880565b90506000610ec643610514565b90506000610ed2611510565b905060005b815181101561119d57818181518110610ef357610ef26129ac565b5b60200260200101519550610f06866118b0565b80610f6b5750600a600085815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b61118a5782156110f7576000600c60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000600c60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555060008111156110f5578773ffffffffffffffffffffffffffffffffffffffff1663099feccb886040518263ffffffff1660e01b815260040161104091906125b9565b602060405180830381865afa15801561105d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110819190612c2c565b73ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050506110f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110eb90612ccb565b60405180910390fd5b5b505b600d60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054856111429190612b28565b94506000600d60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b8080611195906129db565b915050610ed7565b50811561123257600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ec35fe72826040518263ffffffff1660e01b81526004016111ff91906126ee565b600060405180830381600087803b15801561121957600080fd5b505af115801561122d573d6000803e3d6000fd5b505050505b8573ffffffffffffffffffffffffffffffffffffffff1663d45e6273826040518263ffffffff1660e01b815260040161126b91906126ee565b600060405180830381600087803b15801561128557600080fd5b505af1158015611299573d6000803e3d6000fd5b50505050600084111561131b578573ffffffffffffffffffffffffffffffffffffffff166108fc859081150290604051600060405180830381858888f1935050505061131a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161131190612ccb565b60405180910390fd5b5b61132361196c565b505050505050565b6000600160075461133c919061284f565b6007548361134a91906128b2565b149050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146113e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113d99061298c565b60405180910390fd5b6113eb8161054b565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c905bb3582600f546040518363ffffffff1660e01b815260040161144a929190612b5c565b600060405180830381600087803b15801561146457600080fd5b505af1158015611478573d6000803e3d6000fd5b505050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050565b6000600954905090565b60006001600754836114ff9190612af7565b6115099190612b28565b9050919050565b606060035467ffffffffffffffff81111561152e5761152d61233e565b5b60405190808252806020026020018201604052801561155c5781602001602082028036833780820191505090505b50905060005b81518110156115ff576004600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168282815181106115b2576115b16129ac565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505080806115f7906129db565b915050611562565b5090565b60008060019054906101000a900460ff161590508080156116345750600160008054906101000a900460ff1660ff16105b80611661575061164330611d86565b1580156116605750600160008054906101000a900460ff1660ff16145b5b6116a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161169790612d5d565b60405180910390fd5b60016000806101000a81548160ff021916908360ff16021790555080156116dd576001600060016101000a81548160ff0219169083151502179055505b88600060026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555085600681905550846007819055508360088190555082600e8190555081600f81905550801561181c5760008060016101000a81548160ff0219169083151502179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249860016040516118139190612dcf565b60405180910390a15b505050505050505050565b600e5481565b60008060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600160085460075461189491906127f5565b8361189f9190612af7565b6118a99190612b28565b9050919050565b6000600b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020544311159050919050565b6000600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b6000818310156119625781611964565b825b905092915050565b600080600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ea11bf836040518163ffffffff1660e01b8152600401600060405180830381865afa1580156119dc573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611a059190612f44565b9150915060008251905060005b8351811015611b0757611a3e848281518110611a3157611a306129ac565b5b60200260200101516118b0565b15611af4578180611a4e90612fbc565b925050838281518110611a6457611a636129ac565b5b6020026020010151848281518110611a7f57611a7e6129ac565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050828281518110611acc57611acb6129ac565b5b6020026020010151838281518110611ae757611ae66129ac565b5b6020026020010181815250505b8080611aff906129db565b915050611a12565b50808352808252611b188383611da9565b92506000611b296006548551611fa7565b905060008190505b600354811015611c06576004600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600560006004600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81549060ff02191690558080611bfe906129db565b915050611b31565b5060005b81811015611d7157600560006004600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81549060ff02191690556000858281518110611ca957611ca86129ac565b5b602002602001015190506001600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550806004600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550508080611d69906129db565b915050611c0a565b50806003819055504360098190555050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60608251825114611def576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611de690613031565b60405180910390fd5b6000835103611e0057829050611fa1565b6000835167ffffffffffffffff811115611e1d57611e1c61233e565b5b604051908082528060200260200182016040528015611e5657816020015b611e436121ac565b815260200190600190039081611e3b5790505b50905060005b8151811015611ef5576040518060400160405280868381518110611e8357611e826129ac565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff168152602001858381518110611eb957611eb86129ac565b5b6020026020010151815250828281518110611ed757611ed66129ac565b5b60200260200101819052508080611eed906129db565b915050611e5c565b50611f0f81600060018451611f0a919061284f565b611fc0565b5060005b8151811015611f9b57818181518110611f2f57611f2e6129ac565b5b602002602001015160000151858281518110611f4e57611f4d6129ac565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080611f93906129db565b915050611f13565b50839150505b92915050565b6000818310611fb65781611fb8565b825b905092915050565b606060008390506000839050808203611fdd578592505050612178565b60008660028787611fee919061305b565b611ff8919061309e565b876120039190613108565b81518110612014576120136129ac565b5b602002602001015190505b818313612145575b806020015187848151811061203f5761203e6129ac565b5b602002602001015160200151111561206457828061205c9061314c565b935050612027565b5b868281518110612078576120776129ac565b5b602002602001015160200151816020015111156120a257818061209a90613194565b925050612065565b818313612140576120e78784815181106120bf576120be6129ac565b5b60200260200101518884815181106120da576120d96129ac565b5b602002602001015161217f565b8885815181106120fa576120f96129ac565b5b60200260200101898581518110612114576121136129ac565b5b602002602001018290528290525050828061212e9061314c565b935050818061213c90613194565b9250505b61201f565b8186121561215b57612158878784611fc0565b96505b848312156121715761216e878487611fc0565b96505b8693505050505b9392505050565b6121876121ac565b61218f6121ac565b600084905083818095508196505050848492509250509250929050565b604051806040016040528060008152602001600081525090565b6000819050919050565b6121d9816121c6565b82525050565b60006020820190506121f460008301846121d0565b92915050565b6000604051905090565b600080fd5b600080fd5b612217816121c6565b811461222257600080fd5b50565b6000813590506122348161220e565b92915050565b6000602082840312156122505761224f612204565b5b600061225e84828501612225565b91505092915050565b60008115159050919050565b61227c81612267565b82525050565b60006020820190506122976000830184612273565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006122c88261229d565b9050919050565b6122d8816122bd565b81146122e357600080fd5b50565b6000813590506122f5816122cf565b92915050565b60006020828403121561231157612310612204565b5b600061231f848285016122e6565b91505092915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6123768261232d565b810181811067ffffffffffffffff821117156123955761239461233e565b5b80604052505050565b60006123a86121fa565b90506123b4828261236d565b919050565b600067ffffffffffffffff8211156123d4576123d361233e565b5b602082029050602081019050919050565b600080fd5b60006123fd6123f8846123b9565b61239e565b905080838252602082019050602084028301858111156124205761241f6123e5565b5b835b81811015612449578061243588826122e6565b845260208401935050602081019050612422565b5050509392505050565b600082601f83011261246857612467612328565b5b81356124788482602086016123ea565b91505092915050565b60006020828403121561249757612496612204565b5b600082013567ffffffffffffffff8111156124b5576124b4612209565b5b6124c184828501612453565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6124ff81612267565b82525050565b600061251183836124f6565b60208301905092915050565b6000602082019050919050565b6000612535826124ca565b61253f81856124d5565b935061254a836124e6565b8060005b8381101561257b5781516125628882612505565b975061256d8361251d565b92505060018101905061254e565b5085935050505092915050565b600060208201905081810360008301526125a2818461252a565b905092915050565b6125b3816122bd565b82525050565b60006020820190506125ce60008301846125aa565b92915050565b600080604083850312156125eb576125ea612204565b5b600083013567ffffffffffffffff81111561260957612608612209565b5b61261585828601612453565b925050602061262685828601612225565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612665816122bd565b82525050565b6000612677838361265c565b60208301905092915050565b6000602082019050919050565b600061269b82612630565b6126a5818561263b565b93506126b08361264c565b8060005b838110156126e15781516126c8888261266b565b97506126d383612683565b9250506001810190506126b4565b5085935050505092915050565b600060208201905081810360008301526127088184612690565b905092915050565b600080600080600080600080610100898b03121561273157612730612204565b5b600061273f8b828c016122e6565b98505060206127508b828c016122e6565b97505060406127618b828c016122e6565b96505060606127728b828c01612225565b95505060806127838b828c01612225565b94505060a06127948b828c01612225565b93505060c06127a58b828c01612225565b92505060e06127b68b828c01612225565b9150509295985092959890939650565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000612800826121c6565b915061280b836121c6565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612844576128436127c6565b5b828202905092915050565b600061285a826121c6565b9150612865836121c6565b925082820390508181111561287d5761287c6127c6565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006128bd826121c6565b91506128c8836121c6565b9250826128d8576128d7612883565b5b828206905092915050565b600082825260208201905092915050565b7f526f6e696e56616c696461746f725365743a206d6574686f642063616c6c657260008201527f206d75737420626520736c61736820696e64696361746f7220636f6e7472616360208201527f7400000000000000000000000000000000000000000000000000000000000000604082015250565b60006129766041836128e3565b9150612981826128f4565b606082019050919050565b600060208201905081810360008301526129a581612969565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006129e6826121c6565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612a1857612a176127c6565b5b600182019050919050565b7f526f6e696e56616c696461746f725365743a206d6574686f642063616c6c657260008201527f206d75737420626520636f696e62617365000000000000000000000000000000602082015250565b6000612a7f6031836128e3565b9150612a8a82612a23565b604082019050919050565b60006020820190508181036000830152612aae81612a72565b9050919050565b600081519050612ac48161220e565b92915050565b600060208284031215612ae057612adf612204565b5b6000612aee84828501612ab5565b91505092915050565b6000612b02826121c6565b9150612b0d836121c6565b925082612b1d57612b1c612883565b5b828204905092915050565b6000612b33826121c6565b9150612b3e836121c6565b9250828201905080821115612b5657612b556127c6565b5b92915050565b6000604082019050612b7160008301856125aa565b612b7e60208301846121d0565b9392505050565b7f526f6e696e56616c696461746f725365743a206f6e6c7920616c6c6f7765642060008201527f61742074686520656e64206f662065706f636800000000000000000000000000602082015250565b6000612be16033836128e3565b9150612bec82612b85565b604082019050919050565b60006020820190508181036000830152612c1081612bd4565b9050919050565b600081519050612c26816122cf565b92915050565b600060208284031215612c4257612c41612204565b5b6000612c5084828501612c17565b91505092915050565b7f526f6e696e56616c696461746f725365743a20636f756c64206e6f742074726160008201527f6e7366657220524f4e0000000000000000000000000000000000000000000000602082015250565b6000612cb56029836128e3565b9150612cc082612c59565b604082019050919050565b60006020820190508181036000830152612ce481612ca8565b9050919050565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b6000612d47602e836128e3565b9150612d5282612ceb565b604082019050919050565b60006020820190508181036000830152612d7681612d3a565b9050919050565b6000819050919050565b600060ff82169050919050565b6000819050919050565b6000612db9612db4612daf84612d7d565b612d94565b612d87565b9050919050565b612dc981612d9e565b82525050565b6000602082019050612de46000830184612dc0565b92915050565b6000612dfd612df8846123b9565b61239e565b90508083825260208201905060208402830185811115612e2057612e1f6123e5565b5b835b81811015612e495780612e358882612c17565b845260208401935050602081019050612e22565b5050509392505050565b600082601f830112612e6857612e67612328565b5b8151612e78848260208601612dea565b91505092915050565b600067ffffffffffffffff821115612e9c57612e9b61233e565b5b602082029050602081019050919050565b6000612ec0612ebb84612e81565b61239e565b90508083825260208201905060208402830185811115612ee357612ee26123e5565b5b835b81811015612f0c5780612ef88882612ab5565b845260208401935050602081019050612ee5565b5050509392505050565b600082601f830112612f2b57612f2a612328565b5b8151612f3b848260208601612ead565b91505092915050565b60008060408385031215612f5b57612f5a612204565b5b600083015167ffffffffffffffff811115612f7957612f78612209565b5b612f8585828601612e53565b925050602083015167ffffffffffffffff811115612fa657612fa5612209565b5b612fb285828601612f16565b9150509250929050565b6000612fc7826121c6565b915060008203612fda57612fd96127c6565b5b600182039050919050565b7f536f7274696e673a20696e76616c6964206172726179206c656e677468000000600082015250565b600061301b601d836128e3565b915061302682612fe5565b602082019050919050565b6000602082019050818103600083015261304a8161300e565b9050919050565b6000819050919050565b600061306682613051565b915061307183613051565b9250828203905081811260008412168282136000851215161715613098576130976127c6565b5b92915050565b60006130a982613051565b91506130b483613051565b9250826130c4576130c3612883565b5b600160000383147f8000000000000000000000000000000000000000000000000000000000000000831416156130fd576130fc6127c6565b5b828205905092915050565b600061311382613051565b915061311e83613051565b925082820190508281121560008312168382126000841215161715613146576131456127c6565b5b92915050565b600061315782613051565b91507f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613189576131886127c6565b5b600182019050919050565b600061319f82613051565b91507f800000000000000000000000000000000000000000000000000000000000000082036131d1576131d06127c6565b5b60018203905091905056fea264697066735822122066a02006cc27f805b36f00068a836fd7319632c9c99ad555f71ee8a1b73f3fb464736f6c63430008100033", + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"bool[]\",\"name\":\"\",\"type\":\"bool[]\"}],\"name\":\"AddressesPriorityStatusUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"coinbaseAddr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"submittedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"bonusAmount\",\"type\":\"uint256\"}],\"name\":\"BlockRewardSubmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"MaintenanceContractUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"MaxPrioritizedValidatorNumberUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"}],\"name\":\"MaxValidatorCandidateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"MaxValidatorNumberUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"validatorAddr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"MiningRewardDistributed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"NumberOfBlocksInEpochUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"NumberOfEpochsInPeriodUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"coinbaseAddr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rewardAmount\",\"type\":\"uint256\"}],\"name\":\"RewardDeprecated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"SlashIndicatorContractUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"StakingContractUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"StakingRewardDistributed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"StakingVestingContractUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"consensusAddr\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"treasuryAddr\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"candidateIdx\",\"type\":\"uint256\"}],\"name\":\"ValidatorCandidateAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"consensusAddr\",\"type\":\"address\"}],\"name\":\"ValidatorCandidateRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"validatorAddr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"jailedUntil\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"deductedStakingAmount\",\"type\":\"uint256\"}],\"name\":\"ValidatorPunished\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"name\":\"ValidatorSetUpdated\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_consensusAddr\",\"type\":\"address\"},{\"internalType\":\"addresspayable\",\"name\":\"_treasuryAddr\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_commissionRate\",\"type\":\"uint256\"}],\"name\":\"addValidatorCandidate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"epochEndingAt\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"epochOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCandidateInfos\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"consensusAddr\",\"type\":\"address\"},{\"internalType\":\"addresspayable\",\"name\":\"treasuryAddr\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"commissionRate\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"internalType\":\"structICandidateManager.ValidatorCandidate[]\",\"name\":\"_list\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastUpdatedBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"getPriorityStatus\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getValidatorCandidates\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getValidators\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"_validatorList\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__slashIndicatorContract\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__stakingContract\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__stakingVestingContract\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__maintenanceContract\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"__maxValidatorNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"__maxValidatorCandidate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"__maxPrioritizedValidatorNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"__numberOfBlocksInEpoch\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"__numberOfEpochsInPeriod\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_candidate\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"name\":\"isCandidateAdmin\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"isValidator\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"isValidatorCandidate\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_addrList\",\"type\":\"address[]\"}],\"name\":\"jailed\",\"outputs\":[{\"internalType\":\"bool[]\",\"name\":\"_result\",\"type\":\"bool[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maintenanceContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxPrioritizedValidatorNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_maximumPrioritizedValidatorNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxValidatorCandidate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxValidatorNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_maximumValidatorNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"numberOfBlocksInEpoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_numberOfBlocks\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"numberOfEpochsInPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_numberOfEpochs\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"periodEndingAt\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"periodOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_addrList\",\"type\":\"address[]\"},{\"internalType\":\"uint256\",\"name\":\"_period\",\"type\":\"uint256\"}],\"name\":\"rewardDeprecated\",\"outputs\":[{\"internalType\":\"bool[]\",\"name\":\"_result\",\"type\":\"bool[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"setMaintenanceContract\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_number\",\"type\":\"uint256\"}],\"name\":\"setMaxValidatorCandidate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"__maxValidatorNumber\",\"type\":\"uint256\"}],\"name\":\"setMaxValidatorNumber\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"__numberOfBlocksInEpoch\",\"type\":\"uint256\"}],\"name\":\"setNumberOfBlocksInEpoch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"__numberOfEpochsInPeriod\",\"type\":\"uint256\"}],\"name\":\"setNumberOfEpochsInPeriod\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_addrs\",\"type\":\"address[]\"},{\"internalType\":\"bool[]\",\"name\":\"_statuses\",\"type\":\"bool[]\"}],\"name\":\"setPrioritizedAddresses\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"setSlashIndicatorContract\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"setStakingContract\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"setStakingVestingContract\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validatorAddr\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_newJailedUntil\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_slashAmount\",\"type\":\"uint256\"}],\"name\":\"slash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"slashIndicatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakingContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakingVestingContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"submitBlockReward\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"syncCandidates\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_balances\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"validatorCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"wrapUpEpoch\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", + Bin: "0x60806040523480156200001157600080fd5b50620000226200002860201b60201c565b620001d6565b600860019054906101000a900460ff16156200007b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000729062000179565b60405180910390fd5b60ff8016600860009054906101000a900460ff1660ff161015620000f05760ff600860006101000a81548160ff021916908360ff1602179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249860ff604051620000e79190620001b9565b60405180910390a15b565b600082825260208201905092915050565b7f496e697469616c697a61626c653a20636f6e747261637420697320696e69746960008201527f616c697a696e6700000000000000000000000000000000000000000000000000602082015250565b600062000161602783620000f2565b91506200016e8262000103565b604082019050919050565b60006020820190508181036000830152620001948162000152565b9050919050565b600060ff82169050919050565b620001b3816200019b565b82525050565b6000602082019050620001d06000830184620001a8565b92915050565b6162ca80620001e66000396000f3fe6080604052600436106102345760003560e01c806387c891bd1161012e578063d2cb215e116100ab578063e18572bf1161006f578063e18572bf1461083b578063ee99205c14610864578063eeb629a81461088f578063f8549af9146108ba578063facd743b146108f757610243565b8063d2cb215e1461076a578063d33a5ca214610795578063d6fa322c146107be578063d72733fc146107e7578063de7702fb1461081057610243565b8063ad295783116100f2578063ad29578314610697578063b7ab4db5146106c0578063ba77b06c146106eb578063beb3e38214610716578063d09f1ab41461073f57610243565b806387c891bd1461058c5780639dd373b9146105b7578063a0c3f2d2146105e0578063a3d545f51461061d578063ac00125f1461065a57610243565b806352091f17116101bc57806370f81f6c1161018057806370f81f6c146104b657806372e46810146104df5780637593ff71146104e9578063823a7b9c14610526578063865231931461054f57610243565b806352091f17146104005780635248184a1461040a5780635a08482d14610435578063605239a1146104605780636aa1c2ef1461048b57610243565b80633529214b116102035780633529214b1461031b5780634454af9d1461034657806346fe9311146103835780634f2a693f146103ac5780635186dc7e146103d557610243565b806304d971ab1461024d5780630f43a6771461028a57806325a6b529146102b55780632bcf3d15146102f257610243565b3661024357610241610934565b005b61024b610934565b005b34801561025957600080fd5b50610274600480360381019061026f9190614227565b6109ab565b6040516102819190614282565b60405180910390f35b34801561029657600080fd5b5061029f610a46565b6040516102ac91906142b6565b60405180910390f35b3480156102c157600080fd5b506102dc60048036038101906102d791906142fd565b610a4c565b6040516102e99190614282565b60405180910390f35b3480156102fe57600080fd5b506103196004803603810190610314919061432a565b610a83565b005b34801561032757600080fd5b50610330610b04565b60405161033d9190614366565b60405180910390f35b34801561035257600080fd5b5061036d600480360381019061036891906144da565b610b2e565b60405161037a91906145e1565b60405180910390f35b34801561038f57600080fd5b506103aa60048036038101906103a5919061432a565b610b9d565b005b3480156103b857600080fd5b506103d360048036038101906103ce91906142fd565b610c1e565b005b3480156103e157600080fd5b506103ea610c9f565b6040516103f791906142b6565b60405180910390f35b610408610ca9565b005b34801561041657600080fd5b5061041f611047565b60405161042c91906147f9565b60405180910390f35b34801561044157600080fd5b5061044a61130b565b6040516104579190614366565b60405180910390f35b34801561046c57600080fd5b50610475611335565b60405161048291906142b6565b60405180910390f35b34801561049757600080fd5b506104a061133f565b6040516104ad91906142b6565b60405180910390f35b3480156104c257600080fd5b506104dd60048036038101906104d8919061481b565b611349565b005b6104e76116ec565b005b3480156104f557600080fd5b50610510600480360381019061050b91906142fd565b611bc8565b60405161051d9190614282565b60405180910390f35b34801561053257600080fd5b5061054d600480360381019061054891906142fd565b611bef565b005b34801561055b57600080fd5b506105766004803603810190610571919061432a565b611c70565b6040516105839190614282565b60405180910390f35b34801561059857600080fd5b506105a1611cc6565b6040516105ae91906142b6565b60405180910390f35b3480156105c357600080fd5b506105de60048036038101906105d9919061432a565b611cd0565b005b3480156105ec57600080fd5b506106076004803603810190610602919061432a565b611d51565b6040516106149190614282565b60405180910390f35b34801561062957600080fd5b50610644600480360381019061063f91906142fd565b611d9d565b60405161065191906142b6565b60405180910390f35b34801561066657600080fd5b50610681600480360381019061067c919061486e565b611dc0565b60405161068e91906145e1565b60405180910390f35b3480156106a357600080fd5b506106be60048036038101906106b9919061432a565b611e31565b005b3480156106cc57600080fd5b506106d5611eb2565b6040516106e29190614979565b60405180910390f35b3480156106f757600080fd5b50610700611fa5565b60405161070d9190614979565b60405180910390f35b34801561072257600080fd5b5061073d6004803603810190610738919061499b565b612033565b005b34801561074b57600080fd5b506107546121ca565b60405161076191906142b6565b60405180910390f35b34801561077657600080fd5b5061077f6121d4565b60405161078c9190614366565b60405180910390f35b3480156107a157600080fd5b506107bc60048036038101906107b79190614b54565b6121fe565b005b3480156107ca57600080fd5b506107e560048036038101906107e091906142fd565b61246f565b005b3480156107f357600080fd5b5061080e600480360381019061080991906142fd565b6124f0565b005b34801561081c57600080fd5b50610825612571565b6040516108329190614c7b565b60405180910390f35b34801561084757600080fd5b50610862600480360381019061085d9190614cc9565b612770565b005b34801561087057600080fd5b50610879612bb7565b6040516108869190614366565b60405180910390f35b34801561089b57600080fd5b506108a4612be0565b6040516108b191906142b6565b60405180910390f35b3480156108c657600080fd5b506108e160048036038101906108dc91906142fd565b612bea565b6040516108ee91906142b6565b60405180910390f35b34801561090357600080fd5b5061091e6004803603810190610919919061432a565b612c1a565b60405161092b9190614282565b60405180910390f35b61093c610b04565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109a090614dd9565b60405180910390fd5b565b60008173ffffffffffffffffffffffffffffffffffffffff16600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905092915050565b600d5481565b600080600b54600a54610a5f9190614e28565b9050600181610a6e9190614e82565b8184610a7a9190614ee5565b14915050919050565b610a8b612c70565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610af8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aef90614f88565b60405180910390fd5b610b0181612cc7565b50565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060005b8251811015610b9757610b5f838281518110610b5257610b51614fa8565b5b6020026020010151612d42565b828281518110610b7257610b71614fa8565b5b6020026020010190151590811515815250508080610b8f90614fd7565b915050610b33565b50919050565b610ba5612c70565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c12576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c0990614f88565b60405180910390fd5b610c1b81612d8e565b50565b610c26612c70565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c93576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c8a90614f88565b60405180910390fd5b610c9c81612e09565b50565b6000600b54905090565b4173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d17576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d0e90615091565b60405180910390fd5b600034905060008103610d2a5750611045565b6000339050610d3881612c1a565b1580610d495750610d4881612d42565b5b80610d625750610d6181610d5c43612bea565b612e4a565b5b15610da7577f2439a6ac441f1d6b3dbb7827ef6e056822e2261f900cad468012eee4f1f7f31c8183604051610d989291906150b1565b60405180910390a15050611045565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166379ad52846040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e3c91906150ef565b905060008184610e4c919061511c565b905060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000600760008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030154905060006127108483610ecc9190614e28565b610ed69190615150565b905060008185610ee69190614e82565b905081601460008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610f37919061511c565b9250508190555080601560008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610f8d919061511c565b925050819055508373ffffffffffffffffffffffffffffffffffffffff1663b863d71088836040518363ffffffff1660e01b8152600401610fcf9291906150b1565b600060405180830381600087803b158015610fe957600080fd5b505af1158015610ffd573d6000803e3d6000fd5b505050507f0ede5c3be8625943fa64003cd4b91230089411249f3059bac6500873543ca9b187898860405161103493929190615181565b60405180910390a150505050505050505b565b606060058054905067ffffffffffffffff81111561106857611067614397565b5b6040519080825280602002602001820160405280156110a157816020015b61108e6140cd565b8152602001906001900390816110865790505b50905060005b81518110156113075760076000600583815481106110c8576110c7614fa8565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160038201548152602001600482018054611254906151e7565b80601f0160208091040260200160405190810160405280929190818152602001828054611280906151e7565b80156112cd5780601f106112a2576101008083540402835291602001916112cd565b820191906000526020600020905b8154815290600101906020018083116112b057829003601f168201915b5050505050815250508282815181106112e9576112e8614fa8565b5b602002602001018190525080806112ff90614fd7565b9150506110a7565b5090565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600454905090565b6000600a54905090565b3373ffffffffffffffffffffffffffffffffffffffff1661136861130b565b73ffffffffffffffffffffffffffffffffffffffff16146113be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113b5906152b0565b60405180910390fd5b6001601260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061140a43612bea565b815260200190815260200160002060006101000a81548160ff021916908315150217905550601460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009055601560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000905560008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a5885f1d846040518263ffffffff1660e01b815260040161150e9190614366565b600060405180830381600087803b15801561152857600080fd5b505af115801561153c573d6000803e3d6000fd5b5050505060008211156115d65761159282601360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612eb2565b601360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b600081111561166d5760008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c905bb3584836040518363ffffffff1660e01b815260040161163a9291906150b1565b600060405180830381600087803b15801561165457600080fd5b505af1158015611668573d6000803e3d6000fd5b505050505b7f69284547cc931ff0e04d5a21cdfb0748f22a3788269711028ce1d4833900e47483601360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054836040516116df93929190615181565b60405180910390a1505050565b4173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461175a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161175190615091565b60405180910390fd5b61176343611bc8565b6117a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161179990615342565b60405180910390fd5b6117ab43611d9d565b6117b6600c54611d9d565b106117f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117ed906153d4565b60405180910390fd5b43600c8190555060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600080600061183143612bea565b9050600061183e43610a4c565b9050600061184a611eb2565b905060005b8151811015611aba5781818151811061186b5761186a614fa8565b5b6020026020010151955061187e86612d42565b8061188f575061188e8685612e4a565b5b611aa7578215611a16576000601460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050601460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600090556000811115611a14576000600760008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905061199a8183612ecc565b6119d9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119d090615466565b60405180910390fd5b7f9bae506d1374d366cdfa60105473d52dfdbaaae60e55de77bf6ee07f2add0cfb8883604051611a0a9291906150b1565b60405180910390a1505b505b601560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205485611a61919061511c565b9450601560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600090555b8080611ab290614fd7565b91505061184f565b508115611bb8578573ffffffffffffffffffffffffffffffffffffffff1663d45e6273826040518263ffffffff1660e01b8152600401611afa9190614979565b600060405180830381600087803b158015611b1457600080fd5b505af1158015611b28573d6000803e3d6000fd5b505050506000841115611bb757611b40866000612ecc565b611b7f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b76906154f8565b60405180910390fd5b7feb09b8cc1cefa77cd4ec30003e6364cf60afcedd20be8c09f26e717788baf13984604051611bae91906142b6565b60405180910390a15b5b611bc0612f83565b505050505050565b60006001600a54611bd99190614e82565b600a5483611be79190614ee5565b149050919050565b611bf7612c70565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611c64576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c5b90614f88565b60405180910390fd5b611c6d81613394565b50565b6000601060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b6000600c54905090565b611cd8612c70565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d45576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d3c90614f88565b60405180910390fd5b611d4e816133d5565b50565b600080600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414159050919050565b60006001600a5483611daf9190615150565b611db9919061511c565b9050919050565b606060005b8351811015611e2a57611df2848281518110611de457611de3614fa8565b5b602002602001015184612e4a565b828281518110611e0557611e04614fa8565b5b6020026020010190151590811515815250508080611e2290614fd7565b915050611dc5565b5092915050565b611e39612c70565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611ea6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e9d90614f88565b60405180910390fd5b611eaf8161344f565b50565b6060600d5467ffffffffffffffff811115611ed057611ecf614397565b5b604051908082528060200260200182016040528015611efe5781602001602082028036833780820191505090505b50905060005b8151811015611fa157600e600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16828281518110611f5457611f53614fa8565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080611f9990614fd7565b915050611f04565b5090565b6060600580548060200260200160405190810160405280929190818152602001828054801561202957602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311611fdf575b5050505050905090565b6000600860019054906101000a900460ff1615905080801561206757506001600860009054906101000a900460ff1660ff16105b806120965750612076306134ca565b15801561209557506001600860009054906101000a900460ff1660ff16145b5b6120d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120cc9061558a565b60405180910390fd5b6001600860006101000a81548160ff021916908360ff1602179055508015612113576001600860016101000a81548160ff0219169083151502179055505b61211c8a612cc7565b612125896133d5565b61212e8861344f565b61213787612d8e565b61214086613394565b61214985612e09565b612152846134ed565b61215b83613573565b612164826135b4565b80156121be576000600860016101000a81548160ff0219169083151502179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249860016040516121b591906155fc565b60405180910390a15b50505050505050505050565b6000600954905090565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b612206612c70565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612273576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161226a90614f88565b60405180910390fd5b60008251036122b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122ae90615663565b60405180910390fd5b80518251146122fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122f2906156f5565b60405180910390fd5b60005b82518110156124315781818151811061231a57612319614fa8565b5b602002602001015115156010600085848151811061233b5761233a614fa8565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615151461241e578181815181106123a5576123a4614fa8565b5b6020026020010151601060008584815181106123c4576123c3614fa8565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505b808061242990614fd7565b9150506122fe565b507fa52c766fffd3af2ed65a8599973f96a0713c68566068cc057ad25cabd88ed4668282604051612463929190615715565b60405180910390a15050565b612477612c70565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146124e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124db90614f88565b60405180910390fd5b6124ed816135b4565b50565b6124f8612c70565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612565576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161255c90614f88565b60405180910390fd5b61256e81613573565b50565b606060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008173ffffffffffffffffffffffffffffffffffffffff1663ce99b5866040518163ffffffff1660e01b8152600401602060405180830381865afa1580156125e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061260a91906150ef565b90508173ffffffffffffffffffffffffffffffffffffffff16634a5d76cd60056040518263ffffffff1660e01b81526004016126469190615838565b600060405180830381865afa158015612663573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061268c919061591d565b92506000600580549050905060005b8181101561276657828582815181106126b7576126b6614fa8565b5b602002602001015110156127535784826126d090615966565b925082815181106126e4576126e3614fa8565b5b60200260200101518582815181106126ff576126fe614fa8565b5b6020026020010181815250506127526005828154811061272257612721614fa8565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166135f5565b5b808061275e90614fd7565b91505061269b565b5080845250505090565b3373ffffffffffffffffffffffffffffffffffffffff1661278f612bb7565b73ffffffffffffffffffffffffffffffffffffffff16146127e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127dc90615a01565b60405180910390fd5b600060058054905090506127f7611335565b8110612838576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161282f90615a93565b60405180910390fd5b61284184611d51565b15612881576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161287890615b25565b60405180910390fd5b8019600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506005849080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506040518060a001604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff168152602001838152602001600067ffffffffffffffff8111156129a9576129a8614397565b5b6040519080825280601f01601f1916602001820160405280156129db5781602001600182028036833780820191505090505b50815250600760008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301556080820151816004019081612b129190615ce7565b50905050600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f5ea0ccc37694ce2ce1e44e06663c8caff77c1ec661d991e2ece3a6195f879acf60405160405180910390a45050505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000601154905090565b60006001600b54600a54612bfe9190614e28565b83612c099190615150565b612c13919061511c565b9050919050565b6000600f60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b6000612c9e7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610360001b61389c565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507faa5b07dd43aa44c69b70a6a2b9c3fcfed12b6e5f6323596ba7ac91035ab80a4f81604051612d379190614366565b60405180910390a150565b6000601360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020544311159050919050565b80600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f31a33f126a5bae3c5bdf6cfc2cd6dcfffe2fe9634bdb09e21c44762993889e3b81604051612dfe9190614366565b60405180910390a150565b806004819055507f82d5dc32d1b741512ad09c32404d7e7921e8934c6222343d95f55f7a2b9b2ab481604051612e3f91906142b6565b60405180910390a150565b6000601260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060009054906101000a900460ff16905092915050565b600081831015612ec25781612ec4565b825b905092915050565b600081471015612f11576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f0890615e2b565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff1682604051612f3590615e7c565b60006040518083038185875af1925050503d8060008114612f72576040519150601f19603f3d011682016040523d82523d6000602084013e612f77565b606091505b50508091505092915050565b6000612f8d6138a6565b90506000612f9e6009548351613a53565b9050612faa8282613a6c565b80825260008190505b600d5481101561308857600e600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600f6000600e600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81549060ff0219169055808061308090614fd7565b915050612fb3565b50600080600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f0a46709856001436130d8919061511c565b6040518363ffffffff1660e01b81526004016130f5929190615e91565b600060405180830381865afa158015613112573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061313b9190615f6d565b905060005b8381101561334f5781818151811061315b5761315a614fa8565b5b602002602001015161333c57600085828151811061317c5761317b614fa8565b5b60200260200101519050600e600085815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036132005783806131f790614fd7565b9450505061333c565b600f6000600e600087815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81549060ff02191690556001600f60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555080600e600086815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838061333790614fd7565b945050505b808061334790614fd7565b915050613140565b5081600d819055507f6120448f3d4245c1ff708d970c34e1b6484ee22a794ede0bfca2317a97aa8ced846040516133869190614979565b60405180910390a150505050565b806009819055507fb5464c05fd0e0f000c535850116cda2742ee1f7b34384cb920ad7b8e802138b5816040516133ca91906142b6565b60405180910390a150565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f6397f5b135542bb3f477cb346cfab5abdec1251d08dc8f8d4efb4ffe122ea0bf816040516134449190614366565b60405180910390a150565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fc328090a37d855191ab58469296f98f87a851ca57d5cdfd1e9ac3c83e9e7096d816040516134bf9190614366565b60405180910390a150565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600954811115613532576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016135299061604e565b60405180910390fd5b806011819055507fa9588dc77416849bd922605ce4fc806712281ad8a8f32d4238d6c8cca548e15e8160405161356891906142b6565b60405180910390a150565b80600a819055507fbfd285a38b782d8a00e424fb824320ff3d1a698534358d02da611468d59b7808816040516135a991906142b6565b60405180910390a150565b80600b819055507f1d01baa2db15fced4f4e5fcfd4245e65ad9b083c110d26542f4a5f78d5425e77816040516135ea91906142b6565b60405180910390a150565b6000600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050600081036136475750613899565b600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556002820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556003820160009055600482016000613714919061413e565b5050600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000905560006005600160058054905061376f9190614e82565b815481106137805761377f614fa8565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080600583198154811061380757613806614fa8565b5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060058054806138615761386061606e565b5b6001900381819060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055905550505b50565b6000819050919050565b606060006138b2612571565b9050600580548060200260200160405190810160405280929190818152602001828054801561393657602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116138ec575b5050505050915060008251905060005b8351811015613a3b5761397284828151811061396557613964614fa8565b5b6020026020010151612d42565b15613a2857818061398290615966565b92505083828151811061399857613997614fa8565b5b60200260200101518482815181106139b3576139b2614fa8565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050828281518110613a00576139ff614fa8565b5b6020026020010151838281518110613a1b57613a1a614fa8565b5b6020026020010181815250505b8080613a3390614fd7565b915050613946565b50808352808252613a4c8383613ce3565b9250505090565b6000818310613a625781613a64565b825b905092915050565b6000825167ffffffffffffffff811115613a8957613a88614397565b5b604051908082528060200260200182016040528015613ab75781602001602082028036833780820191505090505b50905060008060005b8551811015613c415760106000878381518110613ae057613adf614fa8565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615613bb957601154821015613bb857858181518110613b5257613b51614fa8565b5b6020026020010151868380613b6690614fd7565b945081518110613b7957613b78614fa8565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050613c2e565b5b858181518110613bcc57613bcb614fa8565b5b6020026020010151848480613be090614fd7565b955081518110613bf357613bf2614fa8565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b8080613c3990614fd7565b915050613ac0565b506000915060008190505b84811015613cdb57838380613c6090614fd7565b945081518110613c7357613c72614fa8565b5b6020026020010151868281518110613c8e57613c8d614fa8565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080613cd390614fd7565b915050613c4c565b505050505050565b60608251825114613d29576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613d20906160e9565b60405180910390fd5b6000835103613d3a57829050613edb565b6000835167ffffffffffffffff811115613d5757613d56614397565b5b604051908082528060200260200182016040528015613d9057816020015b613d7d61417e565b815260200190600190039081613d755790505b50905060005b8151811015613e2f576040518060400160405280868381518110613dbd57613dbc614fa8565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff168152602001858381518110613df357613df2614fa8565b5b6020026020010151815250828281518110613e1157613e10614fa8565b5b60200260200101819052508080613e2790614fd7565b915050613d96565b50613e4981600060018451613e449190614e82565b613ee1565b5060005b8151811015613ed557818181518110613e6957613e68614fa8565b5b602002602001015160000151858281518110613e8857613e87614fa8565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080613ecd90614fd7565b915050613e4d565b50839150505b92915050565b606060008390506000839050808203613efe578592505050614099565b60008660028787613f0f9190616113565b613f199190616156565b87613f2491906161c0565b81518110613f3557613f34614fa8565b5b602002602001015190505b818313614066575b8060200151878481518110613f6057613f5f614fa8565b5b6020026020010151602001511115613f85578280613f7d90616204565b935050613f48565b5b868281518110613f9957613f98614fa8565b5b60200260200101516020015181602001511115613fc3578180613fbb9061624c565b925050613f86565b81831361406157614008878481518110613fe057613fdf614fa8565b5b6020026020010151888481518110613ffb57613ffa614fa8565b5b60200260200101516140a0565b88858151811061401b5761401a614fa8565b5b6020026020010189858151811061403557614034614fa8565b5b602002602001018290528290525050828061404f90616204565b935050818061405d9061624c565b9250505b613f40565b8186121561407c57614079878784613ee1565b96505b848312156140925761408f878487613ee1565b96505b8693505050505b9392505050565b6140a861417e565b6140b061417e565b600084905083818095508196505050848492509250509250929050565b6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001606081525090565b50805461414a906151e7565b6000825580601f1061415c575061417b565b601f01602090049060005260206000209081019061417a9190614198565b5b50565b604051806040016040528060008152602001600081525090565b5b808211156141b1576000816000905550600101614199565b5090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006141f4826141c9565b9050919050565b614204816141e9565b811461420f57600080fd5b50565b600081359050614221816141fb565b92915050565b6000806040838503121561423e5761423d6141bf565b5b600061424c85828601614212565b925050602061425d85828601614212565b9150509250929050565b60008115159050919050565b61427c81614267565b82525050565b60006020820190506142976000830184614273565b92915050565b6000819050919050565b6142b08161429d565b82525050565b60006020820190506142cb60008301846142a7565b92915050565b6142da8161429d565b81146142e557600080fd5b50565b6000813590506142f7816142d1565b92915050565b600060208284031215614313576143126141bf565b5b6000614321848285016142e8565b91505092915050565b6000602082840312156143405761433f6141bf565b5b600061434e84828501614212565b91505092915050565b614360816141e9565b82525050565b600060208201905061437b6000830184614357565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6143cf82614386565b810181811067ffffffffffffffff821117156143ee576143ed614397565b5b80604052505050565b60006144016141b5565b905061440d82826143c6565b919050565b600067ffffffffffffffff82111561442d5761442c614397565b5b602082029050602081019050919050565b600080fd5b600061445661445184614412565b6143f7565b905080838252602082019050602084028301858111156144795761447861443e565b5b835b818110156144a2578061448e8882614212565b84526020840193505060208101905061447b565b5050509392505050565b600082601f8301126144c1576144c0614381565b5b81356144d1848260208601614443565b91505092915050565b6000602082840312156144f0576144ef6141bf565b5b600082013567ffffffffffffffff81111561450e5761450d6141c4565b5b61451a848285016144ac565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61455881614267565b82525050565b600061456a838361454f565b60208301905092915050565b6000602082019050919050565b600061458e82614523565b614598818561452e565b93506145a38361453f565b8060005b838110156145d45781516145bb888261455e565b97506145c683614576565b9250506001810190506145a7565b5085935050505092915050565b600060208201905081810360008301526145fb8184614583565b905092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b614638816141e9565b82525050565b6000614649826141c9565b9050919050565b6146598161463e565b82525050565b6146688161429d565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b838110156146a857808201518184015260208101905061468d565b60008484015250505050565b60006146bf8261466e565b6146c98185614679565b93506146d981856020860161468a565b6146e281614386565b840191505092915050565b600060a083016000830151614705600086018261462f565b506020830151614718602086018261462f565b50604083015161472b6040860182614650565b50606083015161473e606086018261465f565b506080830151848203608086015261475682826146b4565b9150508091505092915050565b600061476f83836146ed565b905092915050565b6000602082019050919050565b600061478f82614603565b614799818561460e565b9350836020820285016147ab8561461f565b8060005b858110156147e757848403895281516147c88582614763565b94506147d383614777565b925060208a019950506001810190506147af565b50829750879550505050505092915050565b600060208201905081810360008301526148138184614784565b905092915050565b600080600060608486031215614834576148336141bf565b5b600061484286828701614212565b9350506020614853868287016142e8565b9250506040614864868287016142e8565b9150509250925092565b60008060408385031215614885576148846141bf565b5b600083013567ffffffffffffffff8111156148a3576148a26141c4565b5b6148af858286016144ac565b92505060206148c0858286016142e8565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000614902838361462f565b60208301905092915050565b6000602082019050919050565b6000614926826148ca565b61493081856148d5565b935061493b836148e6565b8060005b8381101561496c57815161495388826148f6565b975061495e8361490e565b92505060018101905061493f565b5085935050505092915050565b60006020820190508181036000830152614993818461491b565b905092915050565b60008060008060008060008060006101208a8c0312156149be576149bd6141bf565b5b60006149cc8c828d01614212565b99505060206149dd8c828d01614212565b98505060406149ee8c828d01614212565b97505060606149ff8c828d01614212565b9650506080614a108c828d016142e8565b95505060a0614a218c828d016142e8565b94505060c0614a328c828d016142e8565b93505060e0614a438c828d016142e8565b925050610100614a558c828d016142e8565b9150509295985092959850929598565b600067ffffffffffffffff821115614a8057614a7f614397565b5b602082029050602081019050919050565b614a9a81614267565b8114614aa557600080fd5b50565b600081359050614ab781614a91565b92915050565b6000614ad0614acb84614a65565b6143f7565b90508083825260208201905060208402830185811115614af357614af261443e565b5b835b81811015614b1c5780614b088882614aa8565b845260208401935050602081019050614af5565b5050509392505050565b600082601f830112614b3b57614b3a614381565b5b8135614b4b848260208601614abd565b91505092915050565b60008060408385031215614b6b57614b6a6141bf565b5b600083013567ffffffffffffffff811115614b8957614b886141c4565b5b614b95858286016144ac565b925050602083013567ffffffffffffffff811115614bb657614bb56141c4565b5b614bc285828601614b26565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000614c04838361465f565b60208301905092915050565b6000602082019050919050565b6000614c2882614bcc565b614c328185614bd7565b9350614c3d83614be8565b8060005b83811015614c6e578151614c558882614bf8565b9750614c6083614c10565b925050600181019050614c41565b5085935050505092915050565b60006020820190508181036000830152614c958184614c1d565b905092915050565b614ca68161463e565b8114614cb157600080fd5b50565b600081359050614cc381614c9d565b92915050565b60008060008060808587031215614ce357614ce26141bf565b5b6000614cf187828801614212565b9450506020614d0287828801614212565b9350506040614d1387828801614cb4565b9250506060614d24878288016142e8565b91505092959194509250565b600082825260208201905092915050565b7f526f6e696e56616c696461746f725365743a206f6e6c7920726563656976657360008201527f20524f4e2066726f6d207374616b696e672076657374696e6720636f6e74726160208201527f6374000000000000000000000000000000000000000000000000000000000000604082015250565b6000614dc3604283614d30565b9150614dce82614d41565b606082019050919050565b60006020820190508181036000830152614df281614db6565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614e338261429d565b9150614e3e8361429d565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614e7757614e76614df9565b5b828202905092915050565b6000614e8d8261429d565b9150614e988361429d565b9250828203905081811115614eb057614eaf614df9565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614ef08261429d565b9150614efb8361429d565b925082614f0b57614f0a614eb6565b5b828206905092915050565b7f48617350726f787941646d696e3a20756e617574686f72697a65642073656e6460008201527f6572000000000000000000000000000000000000000000000000000000000000602082015250565b6000614f72602283614d30565b9150614f7d82614f16565b604082019050919050565b60006020820190508181036000830152614fa181614f65565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000614fe28261429d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361501457615013614df9565b5b600182019050919050565b7f526f6e696e56616c696461746f725365743a206d6574686f642063616c6c657260008201527f206d75737420626520636f696e62617365000000000000000000000000000000602082015250565b600061507b603183614d30565b91506150868261501f565b604082019050919050565b600060208201905081810360008301526150aa8161506e565b9050919050565b60006040820190506150c66000830185614357565b6150d360208301846142a7565b9392505050565b6000815190506150e9816142d1565b92915050565b600060208284031215615105576151046141bf565b5b6000615113848285016150da565b91505092915050565b60006151278261429d565b91506151328361429d565b925082820190508082111561514a57615149614df9565b5b92915050565b600061515b8261429d565b91506151668361429d565b92508261517657615175614eb6565b5b828204905092915050565b60006060820190506151966000830186614357565b6151a360208301856142a7565b6151b060408301846142a7565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806151ff57607f821691505b602082108103615212576152116151b8565b5b50919050565b7f486173536c617368496e64696361746f72436f6e74726163743a206d6574686f60008201527f642063616c6c6572206d75737420626520736c61736820696e64696361746f7260208201527f20636f6e74726163740000000000000000000000000000000000000000000000604082015250565b600061529a604983614d30565b91506152a582615218565b606082019050919050565b600060208201905081810360008301526152c98161528d565b9050919050565b7f526f6e696e56616c696461746f725365743a206f6e6c7920616c6c6f7765642060008201527f61742074686520656e64206f662065706f636800000000000000000000000000602082015250565b600061532c603383614d30565b9150615337826152d0565b604082019050919050565b6000602082019050818103600083015261535b8161531f565b9050919050565b7f526f6e696e56616c696461746f725365743a20717565727920666f7220616c7260008201527f6561647920777261707065642075702065706f63680000000000000000000000602082015250565b60006153be603583614d30565b91506153c982615362565b604082019050919050565b600060208201905081810360008301526153ed816153b1565b9050919050565b7f526f6e696e56616c696461746f725365743a20636f756c64206e6f742074726160008201527f6e7366657220524f4e2074726561737572792061646472657373000000000000602082015250565b6000615450603a83614d30565b915061545b826153f4565b604082019050919050565b6000602082019050818103600083015261547f81615443565b9050919050565b7f526f6e696e56616c696461746f725365743a20636f756c64206e6f742074726160008201527f6e7366657220524f4e20746f207374616b696e6720636f6e7472616374000000602082015250565b60006154e2603d83614d30565b91506154ed82615486565b604082019050919050565b60006020820190508181036000830152615511816154d5565b9050919050565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b6000615574602e83614d30565b915061557f82615518565b604082019050919050565b600060208201905081810360008301526155a381615567565b9050919050565b6000819050919050565b600060ff82169050919050565b6000819050919050565b60006155e66155e16155dc846155aa565b6155c1565b6155b4565b9050919050565b6155f6816155cb565b82525050565b600060208201905061561160008301846155ed565b92915050565b7f526f6e696e56616c696461746f725365743a20656d7074792061727261790000600082015250565b600061564d601e83614d30565b915061565882615617565b602082019050919050565b6000602082019050818103600083015261567c81615640565b9050919050565b7f526f6e696e56616c696461746f725365743a206c656e677468206f662074776f60008201527f20696e70757420617272617973206d69736d6174636865730000000000000000602082015250565b60006156df603883614d30565b91506156ea82615683565b604082019050919050565b6000602082019050818103600083015261570e816156d2565b9050919050565b6000604082019050818103600083015261572f818561491b565b905081810360208301526157438184614583565b90509392505050565b600081549050919050565b60008190508160005260206000209050919050565b60008160001c9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006157ac6157a78361576c565b615779565b9050919050565b60006157bf8254615799565b9050919050565b6000600182019050919050565b60006157de8261574c565b6157e881856148d5565b93506157f383615757565b8060005b8381101561582b57615808826157b3565b61581288826148f6565b975061581d836157c6565b9250506001810190506157f7565b5085935050505092915050565b6000602082019050818103600083015261585281846157d3565b905092915050565b600067ffffffffffffffff82111561587557615874614397565b5b602082029050602081019050919050565b60006158996158948461585a565b6143f7565b905080838252602082019050602084028301858111156158bc576158bb61443e565b5b835b818110156158e557806158d188826150da565b8452602084019350506020810190506158be565b5050509392505050565b600082601f83011261590457615903614381565b5b8151615914848260208601615886565b91505092915050565b600060208284031215615933576159326141bf565b5b600082015167ffffffffffffffff811115615951576159506141c4565b5b61595d848285016158ef565b91505092915050565b60006159718261429d565b91506000820361598457615983614df9565b5b600182039050919050565b7f4861735374616b696e674d616e616765723a206d6574686f642063616c6c657260008201527f206d757374206265207374616b696e6720636f6e747261637400000000000000602082015250565b60006159eb603983614d30565b91506159f68261598f565b604082019050919050565b60006020820190508181036000830152615a1a816159de565b9050919050565b7f43616e6469646174654d616e616765723a2065786365656473206d6178696d7560008201527f6d206e756d626572206f662063616e6469646174657300000000000000000000602082015250565b6000615a7d603683614d30565b9150615a8882615a21565b604082019050919050565b60006020820190508181036000830152615aac81615a70565b9050919050565b7f43616e6469646174654d616e616765723a20717565727920666f7220616c726560008201527f616479206578697374656e742063616e64696461746500000000000000000000602082015250565b6000615b0f603683614d30565b9150615b1a82615ab3565b604082019050919050565b60006020820190508181036000830152615b3e81615b02565b9050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302615ba77fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82615b6a565b615bb18683615b6a565b95508019841693508086168417925050509392505050565b6000615be4615bdf615bda8461429d565b6155c1565b61429d565b9050919050565b6000819050919050565b615bfe83615bc9565b615c12615c0a82615beb565b848454615b77565b825550505050565b600090565b615c27615c1a565b615c32818484615bf5565b505050565b5b81811015615c5657615c4b600082615c1f565b600181019050615c38565b5050565b601f821115615c9b57615c6c81615b45565b615c7584615b5a565b81016020851015615c84578190505b615c98615c9085615b5a565b830182615c37565b50505b505050565b600082821c905092915050565b6000615cbe60001984600802615ca0565b1980831691505092915050565b6000615cd78383615cad565b9150826002028217905092915050565b615cf08261466e565b67ffffffffffffffff811115615d0957615d08614397565b5b615d1382546151e7565b615d1e828285615c5a565b600060209050601f831160018114615d515760008415615d3f578287015190505b615d498582615ccb565b865550615db1565b601f198416615d5f86615b45565b60005b82811015615d8757848901518255600182019150602085019450602081019050615d62565b86831015615da45784890151615da0601f891682615cad565b8355505b6001600288020188555050505b505050505050565b7f524f4e5472616e736665723a20696e73756666696369656e742062616c616e6360008201527f6500000000000000000000000000000000000000000000000000000000000000602082015250565b6000615e15602183614d30565b9150615e2082615db9565b604082019050919050565b60006020820190508181036000830152615e4481615e08565b9050919050565b600081905092915050565b50565b6000615e66600083615e4b565b9150615e7182615e56565b600082019050919050565b6000615e8782615e59565b9150819050919050565b60006040820190508181036000830152615eab818561491b565b9050615eba60208301846142a7565b9392505050565b600081519050615ed081614a91565b92915050565b6000615ee9615ee484614a65565b6143f7565b90508083825260208201905060208402830185811115615f0c57615f0b61443e565b5b835b81811015615f355780615f218882615ec1565b845260208401935050602081019050615f0e565b5050509392505050565b600082601f830112615f5457615f53614381565b5b8151615f64848260208601615ed6565b91505092915050565b600060208284031215615f8357615f826141bf565b5b600082015167ffffffffffffffff811115615fa157615fa06141c4565b5b615fad84828501615f3f565b91505092915050565b7f526f6e696e56616c696461746f725365743a2063616e6e6f7420736574206e7560008201527f6d626572206f66207072696f726974697a65642067726561746572207468616e60208201527f206e756d626572206f66206d61782076616c696461746f727300000000000000604082015250565b6000616038605983614d30565b915061604382615fb6565b606082019050919050565b600060208201905081810360008301526160678161602b565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f536f7274696e673a20696e76616c6964206172726179206c656e677468000000600082015250565b60006160d3601d83614d30565b91506160de8261609d565b602082019050919050565b60006020820190508181036000830152616102816160c6565b9050919050565b6000819050919050565b600061611e82616109565b915061612983616109565b92508282039050818112600084121682821360008512151617156161505761614f614df9565b5b92915050565b600061616182616109565b915061616c83616109565b92508261617c5761617b614eb6565b5b600160000383147f8000000000000000000000000000000000000000000000000000000000000000831416156161b5576161b4614df9565b5b828205905092915050565b60006161cb82616109565b91506161d683616109565b9250828201905082811215600083121683821260008412151617156161fe576161fd614df9565b5b92915050565b600061620f82616109565b91507f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361624157616240614df9565b5b600182019050919050565b600061625782616109565b91507f8000000000000000000000000000000000000000000000000000000000000000820361628957616288614df9565b5b60018203905091905056fea26469706673582212203680cab58b9c20f6796a239eb78e31c55056236c013ebbadaa9a3f08059d033c64736f6c63430008100033", } // RoninValidatorSetABI is the input ABI used to generate the binding from. @@ -263,6 +272,37 @@ func (_RoninValidatorSet *RoninValidatorSetCallerSession) EpochOf(_block *big.In return _RoninValidatorSet.Contract.EpochOf(&_RoninValidatorSet.CallOpts, _block) } +// GetCandidateInfos is a free data retrieval call binding the contract method 0x5248184a. +// +// Solidity: function getCandidateInfos() view returns((address,address,address,uint256,bytes)[] _list) +func (_RoninValidatorSet *RoninValidatorSetCaller) GetCandidateInfos(opts *bind.CallOpts) ([]ICandidateManagerValidatorCandidate, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "getCandidateInfos") + + if err != nil { + return *new([]ICandidateManagerValidatorCandidate), err + } + + out0 := *abi.ConvertType(out[0], new([]ICandidateManagerValidatorCandidate)).(*[]ICandidateManagerValidatorCandidate) + + return out0, err + +} + +// GetCandidateInfos is a free data retrieval call binding the contract method 0x5248184a. +// +// Solidity: function getCandidateInfos() view returns((address,address,address,uint256,bytes)[] _list) +func (_RoninValidatorSet *RoninValidatorSetSession) GetCandidateInfos() ([]ICandidateManagerValidatorCandidate, error) { + return _RoninValidatorSet.Contract.GetCandidateInfos(&_RoninValidatorSet.CallOpts) +} + +// GetCandidateInfos is a free data retrieval call binding the contract method 0x5248184a. +// +// Solidity: function getCandidateInfos() view returns((address,address,address,uint256,bytes)[] _list) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) GetCandidateInfos() ([]ICandidateManagerValidatorCandidate, error) { + return _RoninValidatorSet.Contract.GetCandidateInfos(&_RoninValidatorSet.CallOpts) +} + // GetLastUpdatedBlock is a free data retrieval call binding the contract method 0x87c891bd. // // Solidity: function getLastUpdatedBlock() view returns(uint256) @@ -294,6 +334,68 @@ func (_RoninValidatorSet *RoninValidatorSetCallerSession) GetLastUpdatedBlock() return _RoninValidatorSet.Contract.GetLastUpdatedBlock(&_RoninValidatorSet.CallOpts) } +// GetPriorityStatus is a free data retrieval call binding the contract method 0x86523193. +// +// Solidity: function getPriorityStatus(address _addr) view returns(bool) +func (_RoninValidatorSet *RoninValidatorSetCaller) GetPriorityStatus(opts *bind.CallOpts, _addr common.Address) (bool, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "getPriorityStatus", _addr) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// GetPriorityStatus is a free data retrieval call binding the contract method 0x86523193. +// +// Solidity: function getPriorityStatus(address _addr) view returns(bool) +func (_RoninValidatorSet *RoninValidatorSetSession) GetPriorityStatus(_addr common.Address) (bool, error) { + return _RoninValidatorSet.Contract.GetPriorityStatus(&_RoninValidatorSet.CallOpts, _addr) +} + +// GetPriorityStatus is a free data retrieval call binding the contract method 0x86523193. +// +// Solidity: function getPriorityStatus(address _addr) view returns(bool) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) GetPriorityStatus(_addr common.Address) (bool, error) { + return _RoninValidatorSet.Contract.GetPriorityStatus(&_RoninValidatorSet.CallOpts, _addr) +} + +// GetValidatorCandidates is a free data retrieval call binding the contract method 0xba77b06c. +// +// Solidity: function getValidatorCandidates() view returns(address[]) +func (_RoninValidatorSet *RoninValidatorSetCaller) GetValidatorCandidates(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "getValidatorCandidates") + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +// GetValidatorCandidates is a free data retrieval call binding the contract method 0xba77b06c. +// +// Solidity: function getValidatorCandidates() view returns(address[]) +func (_RoninValidatorSet *RoninValidatorSetSession) GetValidatorCandidates() ([]common.Address, error) { + return _RoninValidatorSet.Contract.GetValidatorCandidates(&_RoninValidatorSet.CallOpts) +} + +// GetValidatorCandidates is a free data retrieval call binding the contract method 0xba77b06c. +// +// Solidity: function getValidatorCandidates() view returns(address[]) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) GetValidatorCandidates() ([]common.Address, error) { + return _RoninValidatorSet.Contract.GetValidatorCandidates(&_RoninValidatorSet.CallOpts) +} + // GetValidators is a free data retrieval call binding the contract method 0xb7ab4db5. // // Solidity: function getValidators() view returns(address[] _validatorList) @@ -325,35 +427,97 @@ func (_RoninValidatorSet *RoninValidatorSetCallerSession) GetValidators() ([]com return _RoninValidatorSet.Contract.GetValidators(&_RoninValidatorSet.CallOpts) } -// GovernanceAdminContract is a free data retrieval call binding the contract method 0xea82f784. +// IsCandidateAdmin is a free data retrieval call binding the contract method 0x04d971ab. // -// Solidity: function governanceAdminContract() view returns(address) -func (_RoninValidatorSet *RoninValidatorSetCaller) GovernanceAdminContract(opts *bind.CallOpts) (common.Address, error) { +// Solidity: function isCandidateAdmin(address _candidate, address _admin) view returns(bool) +func (_RoninValidatorSet *RoninValidatorSetCaller) IsCandidateAdmin(opts *bind.CallOpts, _candidate common.Address, _admin common.Address) (bool, error) { var out []interface{} - err := _RoninValidatorSet.contract.Call(opts, &out, "governanceAdminContract") + err := _RoninValidatorSet.contract.Call(opts, &out, "isCandidateAdmin", _candidate, _admin) if err != nil { - return *new(common.Address), err + return *new(bool), err } - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsCandidateAdmin is a free data retrieval call binding the contract method 0x04d971ab. +// +// Solidity: function isCandidateAdmin(address _candidate, address _admin) view returns(bool) +func (_RoninValidatorSet *RoninValidatorSetSession) IsCandidateAdmin(_candidate common.Address, _admin common.Address) (bool, error) { + return _RoninValidatorSet.Contract.IsCandidateAdmin(&_RoninValidatorSet.CallOpts, _candidate, _admin) +} + +// IsCandidateAdmin is a free data retrieval call binding the contract method 0x04d971ab. +// +// Solidity: function isCandidateAdmin(address _candidate, address _admin) view returns(bool) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) IsCandidateAdmin(_candidate common.Address, _admin common.Address) (bool, error) { + return _RoninValidatorSet.Contract.IsCandidateAdmin(&_RoninValidatorSet.CallOpts, _candidate, _admin) +} + +// IsValidator is a free data retrieval call binding the contract method 0xfacd743b. +// +// Solidity: function isValidator(address _addr) view returns(bool) +func (_RoninValidatorSet *RoninValidatorSetCaller) IsValidator(opts *bind.CallOpts, _addr common.Address) (bool, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "isValidator", _addr) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsValidator is a free data retrieval call binding the contract method 0xfacd743b. +// +// Solidity: function isValidator(address _addr) view returns(bool) +func (_RoninValidatorSet *RoninValidatorSetSession) IsValidator(_addr common.Address) (bool, error) { + return _RoninValidatorSet.Contract.IsValidator(&_RoninValidatorSet.CallOpts, _addr) +} + +// IsValidator is a free data retrieval call binding the contract method 0xfacd743b. +// +// Solidity: function isValidator(address _addr) view returns(bool) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) IsValidator(_addr common.Address) (bool, error) { + return _RoninValidatorSet.Contract.IsValidator(&_RoninValidatorSet.CallOpts, _addr) +} + +// IsValidatorCandidate is a free data retrieval call binding the contract method 0xa0c3f2d2. +// +// Solidity: function isValidatorCandidate(address _addr) view returns(bool) +func (_RoninValidatorSet *RoninValidatorSetCaller) IsValidatorCandidate(opts *bind.CallOpts, _addr common.Address) (bool, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "isValidatorCandidate", _addr) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) return out0, err } -// GovernanceAdminContract is a free data retrieval call binding the contract method 0xea82f784. +// IsValidatorCandidate is a free data retrieval call binding the contract method 0xa0c3f2d2. // -// Solidity: function governanceAdminContract() view returns(address) -func (_RoninValidatorSet *RoninValidatorSetSession) GovernanceAdminContract() (common.Address, error) { - return _RoninValidatorSet.Contract.GovernanceAdminContract(&_RoninValidatorSet.CallOpts) +// Solidity: function isValidatorCandidate(address _addr) view returns(bool) +func (_RoninValidatorSet *RoninValidatorSetSession) IsValidatorCandidate(_addr common.Address) (bool, error) { + return _RoninValidatorSet.Contract.IsValidatorCandidate(&_RoninValidatorSet.CallOpts, _addr) } -// GovernanceAdminContract is a free data retrieval call binding the contract method 0xea82f784. +// IsValidatorCandidate is a free data retrieval call binding the contract method 0xa0c3f2d2. // -// Solidity: function governanceAdminContract() view returns(address) -func (_RoninValidatorSet *RoninValidatorSetCallerSession) GovernanceAdminContract() (common.Address, error) { - return _RoninValidatorSet.Contract.GovernanceAdminContract(&_RoninValidatorSet.CallOpts) +// Solidity: function isValidatorCandidate(address _addr) view returns(bool) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) IsValidatorCandidate(_addr common.Address) (bool, error) { + return _RoninValidatorSet.Contract.IsValidatorCandidate(&_RoninValidatorSet.CallOpts, _addr) } // Jailed is a free data retrieval call binding the contract method 0x4454af9d. @@ -387,35 +551,128 @@ func (_RoninValidatorSet *RoninValidatorSetCallerSession) Jailed(_addrList []com return _RoninValidatorSet.Contract.Jailed(&_RoninValidatorSet.CallOpts, _addrList) } -// NoPendingReward is a free data retrieval call binding the contract method 0x71e594b3. +// MaintenanceContract is a free data retrieval call binding the contract method 0xd2cb215e. // -// Solidity: function noPendingReward(address[] _addrList, uint256 _period) view returns(bool[] _result) -func (_RoninValidatorSet *RoninValidatorSetCaller) NoPendingReward(opts *bind.CallOpts, _addrList []common.Address, _period *big.Int) ([]bool, error) { +// Solidity: function maintenanceContract() view returns(address) +func (_RoninValidatorSet *RoninValidatorSetCaller) MaintenanceContract(opts *bind.CallOpts) (common.Address, error) { var out []interface{} - err := _RoninValidatorSet.contract.Call(opts, &out, "noPendingReward", _addrList, _period) + err := _RoninValidatorSet.contract.Call(opts, &out, "maintenanceContract") if err != nil { - return *new([]bool), err + return *new(common.Address), err } - out0 := *abi.ConvertType(out[0], new([]bool)).(*[]bool) + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// MaintenanceContract is a free data retrieval call binding the contract method 0xd2cb215e. +// +// Solidity: function maintenanceContract() view returns(address) +func (_RoninValidatorSet *RoninValidatorSetSession) MaintenanceContract() (common.Address, error) { + return _RoninValidatorSet.Contract.MaintenanceContract(&_RoninValidatorSet.CallOpts) +} + +// MaintenanceContract is a free data retrieval call binding the contract method 0xd2cb215e. +// +// Solidity: function maintenanceContract() view returns(address) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) MaintenanceContract() (common.Address, error) { + return _RoninValidatorSet.Contract.MaintenanceContract(&_RoninValidatorSet.CallOpts) +} + +// MaxPrioritizedValidatorNumber is a free data retrieval call binding the contract method 0xeeb629a8. +// +// Solidity: function maxPrioritizedValidatorNumber() view returns(uint256 _maximumPrioritizedValidatorNumber) +func (_RoninValidatorSet *RoninValidatorSetCaller) MaxPrioritizedValidatorNumber(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "maxPrioritizedValidatorNumber") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// MaxPrioritizedValidatorNumber is a free data retrieval call binding the contract method 0xeeb629a8. +// +// Solidity: function maxPrioritizedValidatorNumber() view returns(uint256 _maximumPrioritizedValidatorNumber) +func (_RoninValidatorSet *RoninValidatorSetSession) MaxPrioritizedValidatorNumber() (*big.Int, error) { + return _RoninValidatorSet.Contract.MaxPrioritizedValidatorNumber(&_RoninValidatorSet.CallOpts) +} + +// MaxPrioritizedValidatorNumber is a free data retrieval call binding the contract method 0xeeb629a8. +// +// Solidity: function maxPrioritizedValidatorNumber() view returns(uint256 _maximumPrioritizedValidatorNumber) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) MaxPrioritizedValidatorNumber() (*big.Int, error) { + return _RoninValidatorSet.Contract.MaxPrioritizedValidatorNumber(&_RoninValidatorSet.CallOpts) +} + +// MaxValidatorCandidate is a free data retrieval call binding the contract method 0x605239a1. +// +// Solidity: function maxValidatorCandidate() view returns(uint256) +func (_RoninValidatorSet *RoninValidatorSetCaller) MaxValidatorCandidate(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "maxValidatorCandidate") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// MaxValidatorCandidate is a free data retrieval call binding the contract method 0x605239a1. +// +// Solidity: function maxValidatorCandidate() view returns(uint256) +func (_RoninValidatorSet *RoninValidatorSetSession) MaxValidatorCandidate() (*big.Int, error) { + return _RoninValidatorSet.Contract.MaxValidatorCandidate(&_RoninValidatorSet.CallOpts) +} + +// MaxValidatorCandidate is a free data retrieval call binding the contract method 0x605239a1. +// +// Solidity: function maxValidatorCandidate() view returns(uint256) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) MaxValidatorCandidate() (*big.Int, error) { + return _RoninValidatorSet.Contract.MaxValidatorCandidate(&_RoninValidatorSet.CallOpts) +} + +// MaxValidatorNumber is a free data retrieval call binding the contract method 0xd09f1ab4. +// +// Solidity: function maxValidatorNumber() view returns(uint256 _maximumValidatorNumber) +func (_RoninValidatorSet *RoninValidatorSetCaller) MaxValidatorNumber(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "maxValidatorNumber") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) return out0, err } -// NoPendingReward is a free data retrieval call binding the contract method 0x71e594b3. +// MaxValidatorNumber is a free data retrieval call binding the contract method 0xd09f1ab4. // -// Solidity: function noPendingReward(address[] _addrList, uint256 _period) view returns(bool[] _result) -func (_RoninValidatorSet *RoninValidatorSetSession) NoPendingReward(_addrList []common.Address, _period *big.Int) ([]bool, error) { - return _RoninValidatorSet.Contract.NoPendingReward(&_RoninValidatorSet.CallOpts, _addrList, _period) +// Solidity: function maxValidatorNumber() view returns(uint256 _maximumValidatorNumber) +func (_RoninValidatorSet *RoninValidatorSetSession) MaxValidatorNumber() (*big.Int, error) { + return _RoninValidatorSet.Contract.MaxValidatorNumber(&_RoninValidatorSet.CallOpts) } -// NoPendingReward is a free data retrieval call binding the contract method 0x71e594b3. +// MaxValidatorNumber is a free data retrieval call binding the contract method 0xd09f1ab4. // -// Solidity: function noPendingReward(address[] _addrList, uint256 _period) view returns(bool[] _result) -func (_RoninValidatorSet *RoninValidatorSetCallerSession) NoPendingReward(_addrList []common.Address, _period *big.Int) ([]bool, error) { - return _RoninValidatorSet.Contract.NoPendingReward(&_RoninValidatorSet.CallOpts, _addrList, _period) +// Solidity: function maxValidatorNumber() view returns(uint256 _maximumValidatorNumber) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) MaxValidatorNumber() (*big.Int, error) { + return _RoninValidatorSet.Contract.MaxValidatorNumber(&_RoninValidatorSet.CallOpts) } // NumberOfBlocksInEpoch is a free data retrieval call binding the contract method 0x6aa1c2ef. @@ -542,66 +799,35 @@ func (_RoninValidatorSet *RoninValidatorSetCallerSession) PeriodOf(_block *big.I return _RoninValidatorSet.Contract.PeriodOf(&_RoninValidatorSet.CallOpts, _block) } -// SlashDoubleSignAmount is a free data retrieval call binding the contract method 0x6d14c4e5. +// RewardDeprecated is a free data retrieval call binding the contract method 0xac00125f. // -// Solidity: function slashDoubleSignAmount() view returns(uint256) -func (_RoninValidatorSet *RoninValidatorSetCaller) SlashDoubleSignAmount(opts *bind.CallOpts) (*big.Int, error) { +// Solidity: function rewardDeprecated(address[] _addrList, uint256 _period) view returns(bool[] _result) +func (_RoninValidatorSet *RoninValidatorSetCaller) RewardDeprecated(opts *bind.CallOpts, _addrList []common.Address, _period *big.Int) ([]bool, error) { var out []interface{} - err := _RoninValidatorSet.contract.Call(opts, &out, "slashDoubleSignAmount") + err := _RoninValidatorSet.contract.Call(opts, &out, "rewardDeprecated", _addrList, _period) if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// SlashDoubleSignAmount is a free data retrieval call binding the contract method 0x6d14c4e5. -// -// Solidity: function slashDoubleSignAmount() view returns(uint256) -func (_RoninValidatorSet *RoninValidatorSetSession) SlashDoubleSignAmount() (*big.Int, error) { - return _RoninValidatorSet.Contract.SlashDoubleSignAmount(&_RoninValidatorSet.CallOpts) -} - -// SlashDoubleSignAmount is a free data retrieval call binding the contract method 0x6d14c4e5. -// -// Solidity: function slashDoubleSignAmount() view returns(uint256) -func (_RoninValidatorSet *RoninValidatorSetCallerSession) SlashDoubleSignAmount() (*big.Int, error) { - return _RoninValidatorSet.Contract.SlashDoubleSignAmount(&_RoninValidatorSet.CallOpts) -} - -// SlashFelonyAmount is a free data retrieval call binding the contract method 0xdfe484cb. -// -// Solidity: function slashFelonyAmount() view returns(uint256) -func (_RoninValidatorSet *RoninValidatorSetCaller) SlashFelonyAmount(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _RoninValidatorSet.contract.Call(opts, &out, "slashFelonyAmount") - - if err != nil { - return *new(*big.Int), err + return *new([]bool), err } - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + out0 := *abi.ConvertType(out[0], new([]bool)).(*[]bool) return out0, err } -// SlashFelonyAmount is a free data retrieval call binding the contract method 0xdfe484cb. +// RewardDeprecated is a free data retrieval call binding the contract method 0xac00125f. // -// Solidity: function slashFelonyAmount() view returns(uint256) -func (_RoninValidatorSet *RoninValidatorSetSession) SlashFelonyAmount() (*big.Int, error) { - return _RoninValidatorSet.Contract.SlashFelonyAmount(&_RoninValidatorSet.CallOpts) +// Solidity: function rewardDeprecated(address[] _addrList, uint256 _period) view returns(bool[] _result) +func (_RoninValidatorSet *RoninValidatorSetSession) RewardDeprecated(_addrList []common.Address, _period *big.Int) ([]bool, error) { + return _RoninValidatorSet.Contract.RewardDeprecated(&_RoninValidatorSet.CallOpts, _addrList, _period) } -// SlashFelonyAmount is a free data retrieval call binding the contract method 0xdfe484cb. +// RewardDeprecated is a free data retrieval call binding the contract method 0xac00125f. // -// Solidity: function slashFelonyAmount() view returns(uint256) -func (_RoninValidatorSet *RoninValidatorSetCallerSession) SlashFelonyAmount() (*big.Int, error) { - return _RoninValidatorSet.Contract.SlashFelonyAmount(&_RoninValidatorSet.CallOpts) +// Solidity: function rewardDeprecated(address[] _addrList, uint256 _period) view returns(bool[] _result) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) RewardDeprecated(_addrList []common.Address, _period *big.Int) ([]bool, error) { + return _RoninValidatorSet.Contract.RewardDeprecated(&_RoninValidatorSet.CallOpts, _addrList, _period) } // SlashIndicatorContract is a free data retrieval call binding the contract method 0x5a08482d. @@ -666,6 +892,37 @@ func (_RoninValidatorSet *RoninValidatorSetCallerSession) StakingContract() (com return _RoninValidatorSet.Contract.StakingContract(&_RoninValidatorSet.CallOpts) } +// StakingVestingContract is a free data retrieval call binding the contract method 0x3529214b. +// +// Solidity: function stakingVestingContract() view returns(address) +func (_RoninValidatorSet *RoninValidatorSetCaller) StakingVestingContract(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _RoninValidatorSet.contract.Call(opts, &out, "stakingVestingContract") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// StakingVestingContract is a free data retrieval call binding the contract method 0x3529214b. +// +// Solidity: function stakingVestingContract() view returns(address) +func (_RoninValidatorSet *RoninValidatorSetSession) StakingVestingContract() (common.Address, error) { + return _RoninValidatorSet.Contract.StakingVestingContract(&_RoninValidatorSet.CallOpts) +} + +// StakingVestingContract is a free data retrieval call binding the contract method 0x3529214b. +// +// Solidity: function stakingVestingContract() view returns(address) +func (_RoninValidatorSet *RoninValidatorSetCallerSession) StakingVestingContract() (common.Address, error) { + return _RoninValidatorSet.Contract.StakingVestingContract(&_RoninValidatorSet.CallOpts) +} + // ValidatorCount is a free data retrieval call binding the contract method 0x0f43a677. // // Solidity: function validatorCount() view returns(uint256) @@ -697,161 +954,2569 @@ func (_RoninValidatorSet *RoninValidatorSetCallerSession) ValidatorCount() (*big return _RoninValidatorSet.Contract.ValidatorCount(&_RoninValidatorSet.CallOpts) } -// Initialize is a paid mutator transaction binding the contract method 0xdf8fa430. +// AddValidatorCandidate is a paid mutator transaction binding the contract method 0xe18572bf. // -// Solidity: function initialize(address __governanceAdminContract, address __slashIndicatorContract, address __stakingContract, uint256 __maxValidatorNumber, uint256 __numberOfBlocksInEpoch, uint256 __numberOfEpochsInPeriod, uint256 _slashFelonyAmount, uint256 _slashDoubleSignAmount) returns() -func (_RoninValidatorSet *RoninValidatorSetTransactor) Initialize(opts *bind.TransactOpts, __governanceAdminContract common.Address, __slashIndicatorContract common.Address, __stakingContract common.Address, __maxValidatorNumber *big.Int, __numberOfBlocksInEpoch *big.Int, __numberOfEpochsInPeriod *big.Int, _slashFelonyAmount *big.Int, _slashDoubleSignAmount *big.Int) (*types.Transaction, error) { - return _RoninValidatorSet.contract.Transact(opts, "initialize", __governanceAdminContract, __slashIndicatorContract, __stakingContract, __maxValidatorNumber, __numberOfBlocksInEpoch, __numberOfEpochsInPeriod, _slashFelonyAmount, _slashDoubleSignAmount) +// Solidity: function addValidatorCandidate(address _admin, address _consensusAddr, address _treasuryAddr, uint256 _commissionRate) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactor) AddValidatorCandidate(opts *bind.TransactOpts, _admin common.Address, _consensusAddr common.Address, _treasuryAddr common.Address, _commissionRate *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.contract.Transact(opts, "addValidatorCandidate", _admin, _consensusAddr, _treasuryAddr, _commissionRate) } -// Initialize is a paid mutator transaction binding the contract method 0xdf8fa430. +// AddValidatorCandidate is a paid mutator transaction binding the contract method 0xe18572bf. // -// Solidity: function initialize(address __governanceAdminContract, address __slashIndicatorContract, address __stakingContract, uint256 __maxValidatorNumber, uint256 __numberOfBlocksInEpoch, uint256 __numberOfEpochsInPeriod, uint256 _slashFelonyAmount, uint256 _slashDoubleSignAmount) returns() -func (_RoninValidatorSet *RoninValidatorSetSession) Initialize(__governanceAdminContract common.Address, __slashIndicatorContract common.Address, __stakingContract common.Address, __maxValidatorNumber *big.Int, __numberOfBlocksInEpoch *big.Int, __numberOfEpochsInPeriod *big.Int, _slashFelonyAmount *big.Int, _slashDoubleSignAmount *big.Int) (*types.Transaction, error) { - return _RoninValidatorSet.Contract.Initialize(&_RoninValidatorSet.TransactOpts, __governanceAdminContract, __slashIndicatorContract, __stakingContract, __maxValidatorNumber, __numberOfBlocksInEpoch, __numberOfEpochsInPeriod, _slashFelonyAmount, _slashDoubleSignAmount) +// Solidity: function addValidatorCandidate(address _admin, address _consensusAddr, address _treasuryAddr, uint256 _commissionRate) returns() +func (_RoninValidatorSet *RoninValidatorSetSession) AddValidatorCandidate(_admin common.Address, _consensusAddr common.Address, _treasuryAddr common.Address, _commissionRate *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.AddValidatorCandidate(&_RoninValidatorSet.TransactOpts, _admin, _consensusAddr, _treasuryAddr, _commissionRate) } -// Initialize is a paid mutator transaction binding the contract method 0xdf8fa430. +// AddValidatorCandidate is a paid mutator transaction binding the contract method 0xe18572bf. // -// Solidity: function initialize(address __governanceAdminContract, address __slashIndicatorContract, address __stakingContract, uint256 __maxValidatorNumber, uint256 __numberOfBlocksInEpoch, uint256 __numberOfEpochsInPeriod, uint256 _slashFelonyAmount, uint256 _slashDoubleSignAmount) returns() -func (_RoninValidatorSet *RoninValidatorSetTransactorSession) Initialize(__governanceAdminContract common.Address, __slashIndicatorContract common.Address, __stakingContract common.Address, __maxValidatorNumber *big.Int, __numberOfBlocksInEpoch *big.Int, __numberOfEpochsInPeriod *big.Int, _slashFelonyAmount *big.Int, _slashDoubleSignAmount *big.Int) (*types.Transaction, error) { - return _RoninValidatorSet.Contract.Initialize(&_RoninValidatorSet.TransactOpts, __governanceAdminContract, __slashIndicatorContract, __stakingContract, __maxValidatorNumber, __numberOfBlocksInEpoch, __numberOfEpochsInPeriod, _slashFelonyAmount, _slashDoubleSignAmount) +// Solidity: function addValidatorCandidate(address _admin, address _consensusAddr, address _treasuryAddr, uint256 _commissionRate) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) AddValidatorCandidate(_admin common.Address, _consensusAddr common.Address, _treasuryAddr common.Address, _commissionRate *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.AddValidatorCandidate(&_RoninValidatorSet.TransactOpts, _admin, _consensusAddr, _treasuryAddr, _commissionRate) } -// SlashDoubleSign is a paid mutator transaction binding the contract method 0x7ae46af3. +// Initialize is a paid mutator transaction binding the contract method 0xbeb3e382. // -// Solidity: function slashDoubleSign(address _validatorAddr) returns() -func (_RoninValidatorSet *RoninValidatorSetTransactor) SlashDoubleSign(opts *bind.TransactOpts, _validatorAddr common.Address) (*types.Transaction, error) { - return _RoninValidatorSet.contract.Transact(opts, "slashDoubleSign", _validatorAddr) +// Solidity: function initialize(address __slashIndicatorContract, address __stakingContract, address __stakingVestingContract, address __maintenanceContract, uint256 __maxValidatorNumber, uint256 __maxValidatorCandidate, uint256 __maxPrioritizedValidatorNumber, uint256 __numberOfBlocksInEpoch, uint256 __numberOfEpochsInPeriod) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactor) Initialize(opts *bind.TransactOpts, __slashIndicatorContract common.Address, __stakingContract common.Address, __stakingVestingContract common.Address, __maintenanceContract common.Address, __maxValidatorNumber *big.Int, __maxValidatorCandidate *big.Int, __maxPrioritizedValidatorNumber *big.Int, __numberOfBlocksInEpoch *big.Int, __numberOfEpochsInPeriod *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.contract.Transact(opts, "initialize", __slashIndicatorContract, __stakingContract, __stakingVestingContract, __maintenanceContract, __maxValidatorNumber, __maxValidatorCandidate, __maxPrioritizedValidatorNumber, __numberOfBlocksInEpoch, __numberOfEpochsInPeriod) } -// SlashDoubleSign is a paid mutator transaction binding the contract method 0x7ae46af3. +// Initialize is a paid mutator transaction binding the contract method 0xbeb3e382. // -// Solidity: function slashDoubleSign(address _validatorAddr) returns() -func (_RoninValidatorSet *RoninValidatorSetSession) SlashDoubleSign(_validatorAddr common.Address) (*types.Transaction, error) { - return _RoninValidatorSet.Contract.SlashDoubleSign(&_RoninValidatorSet.TransactOpts, _validatorAddr) +// Solidity: function initialize(address __slashIndicatorContract, address __stakingContract, address __stakingVestingContract, address __maintenanceContract, uint256 __maxValidatorNumber, uint256 __maxValidatorCandidate, uint256 __maxPrioritizedValidatorNumber, uint256 __numberOfBlocksInEpoch, uint256 __numberOfEpochsInPeriod) returns() +func (_RoninValidatorSet *RoninValidatorSetSession) Initialize(__slashIndicatorContract common.Address, __stakingContract common.Address, __stakingVestingContract common.Address, __maintenanceContract common.Address, __maxValidatorNumber *big.Int, __maxValidatorCandidate *big.Int, __maxPrioritizedValidatorNumber *big.Int, __numberOfBlocksInEpoch *big.Int, __numberOfEpochsInPeriod *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.Initialize(&_RoninValidatorSet.TransactOpts, __slashIndicatorContract, __stakingContract, __stakingVestingContract, __maintenanceContract, __maxValidatorNumber, __maxValidatorCandidate, __maxPrioritizedValidatorNumber, __numberOfBlocksInEpoch, __numberOfEpochsInPeriod) } -// SlashDoubleSign is a paid mutator transaction binding the contract method 0x7ae46af3. +// Initialize is a paid mutator transaction binding the contract method 0xbeb3e382. // -// Solidity: function slashDoubleSign(address _validatorAddr) returns() -func (_RoninValidatorSet *RoninValidatorSetTransactorSession) SlashDoubleSign(_validatorAddr common.Address) (*types.Transaction, error) { - return _RoninValidatorSet.Contract.SlashDoubleSign(&_RoninValidatorSet.TransactOpts, _validatorAddr) +// Solidity: function initialize(address __slashIndicatorContract, address __stakingContract, address __stakingVestingContract, address __maintenanceContract, uint256 __maxValidatorNumber, uint256 __maxValidatorCandidate, uint256 __maxPrioritizedValidatorNumber, uint256 __numberOfBlocksInEpoch, uint256 __numberOfEpochsInPeriod) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) Initialize(__slashIndicatorContract common.Address, __stakingContract common.Address, __stakingVestingContract common.Address, __maintenanceContract common.Address, __maxValidatorNumber *big.Int, __maxValidatorCandidate *big.Int, __maxPrioritizedValidatorNumber *big.Int, __numberOfBlocksInEpoch *big.Int, __numberOfEpochsInPeriod *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.Initialize(&_RoninValidatorSet.TransactOpts, __slashIndicatorContract, __stakingContract, __stakingVestingContract, __maintenanceContract, __maxValidatorNumber, __maxValidatorCandidate, __maxPrioritizedValidatorNumber, __numberOfBlocksInEpoch, __numberOfEpochsInPeriod) } -// SlashFelony is a paid mutator transaction binding the contract method 0x722d298f. +// SetMaintenanceContract is a paid mutator transaction binding the contract method 0x46fe9311. // -// Solidity: function slashFelony(address _validatorAddr) returns() -func (_RoninValidatorSet *RoninValidatorSetTransactor) SlashFelony(opts *bind.TransactOpts, _validatorAddr common.Address) (*types.Transaction, error) { - return _RoninValidatorSet.contract.Transact(opts, "slashFelony", _validatorAddr) +// Solidity: function setMaintenanceContract(address _addr) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactor) SetMaintenanceContract(opts *bind.TransactOpts, _addr common.Address) (*types.Transaction, error) { + return _RoninValidatorSet.contract.Transact(opts, "setMaintenanceContract", _addr) } -// SlashFelony is a paid mutator transaction binding the contract method 0x722d298f. +// SetMaintenanceContract is a paid mutator transaction binding the contract method 0x46fe9311. // -// Solidity: function slashFelony(address _validatorAddr) returns() -func (_RoninValidatorSet *RoninValidatorSetSession) SlashFelony(_validatorAddr common.Address) (*types.Transaction, error) { - return _RoninValidatorSet.Contract.SlashFelony(&_RoninValidatorSet.TransactOpts, _validatorAddr) +// Solidity: function setMaintenanceContract(address _addr) returns() +func (_RoninValidatorSet *RoninValidatorSetSession) SetMaintenanceContract(_addr common.Address) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SetMaintenanceContract(&_RoninValidatorSet.TransactOpts, _addr) } -// SlashFelony is a paid mutator transaction binding the contract method 0x722d298f. +// SetMaintenanceContract is a paid mutator transaction binding the contract method 0x46fe9311. // -// Solidity: function slashFelony(address _validatorAddr) returns() -func (_RoninValidatorSet *RoninValidatorSetTransactorSession) SlashFelony(_validatorAddr common.Address) (*types.Transaction, error) { - return _RoninValidatorSet.Contract.SlashFelony(&_RoninValidatorSet.TransactOpts, _validatorAddr) +// Solidity: function setMaintenanceContract(address _addr) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) SetMaintenanceContract(_addr common.Address) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SetMaintenanceContract(&_RoninValidatorSet.TransactOpts, _addr) } -// SlashMisdemeanor is a paid mutator transaction binding the contract method 0x3dc56e09. +// SetMaxValidatorCandidate is a paid mutator transaction binding the contract method 0x4f2a693f. // -// Solidity: function slashMisdemeanor(address _validatorAddr) returns() -func (_RoninValidatorSet *RoninValidatorSetTransactor) SlashMisdemeanor(opts *bind.TransactOpts, _validatorAddr common.Address) (*types.Transaction, error) { - return _RoninValidatorSet.contract.Transact(opts, "slashMisdemeanor", _validatorAddr) +// Solidity: function setMaxValidatorCandidate(uint256 _number) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactor) SetMaxValidatorCandidate(opts *bind.TransactOpts, _number *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.contract.Transact(opts, "setMaxValidatorCandidate", _number) } -// SlashMisdemeanor is a paid mutator transaction binding the contract method 0x3dc56e09. +// SetMaxValidatorCandidate is a paid mutator transaction binding the contract method 0x4f2a693f. // -// Solidity: function slashMisdemeanor(address _validatorAddr) returns() -func (_RoninValidatorSet *RoninValidatorSetSession) SlashMisdemeanor(_validatorAddr common.Address) (*types.Transaction, error) { - return _RoninValidatorSet.Contract.SlashMisdemeanor(&_RoninValidatorSet.TransactOpts, _validatorAddr) +// Solidity: function setMaxValidatorCandidate(uint256 _number) returns() +func (_RoninValidatorSet *RoninValidatorSetSession) SetMaxValidatorCandidate(_number *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SetMaxValidatorCandidate(&_RoninValidatorSet.TransactOpts, _number) } -// SlashMisdemeanor is a paid mutator transaction binding the contract method 0x3dc56e09. +// SetMaxValidatorCandidate is a paid mutator transaction binding the contract method 0x4f2a693f. // -// Solidity: function slashMisdemeanor(address _validatorAddr) returns() -func (_RoninValidatorSet *RoninValidatorSetTransactorSession) SlashMisdemeanor(_validatorAddr common.Address) (*types.Transaction, error) { - return _RoninValidatorSet.Contract.SlashMisdemeanor(&_RoninValidatorSet.TransactOpts, _validatorAddr) +// Solidity: function setMaxValidatorCandidate(uint256 _number) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) SetMaxValidatorCandidate(_number *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SetMaxValidatorCandidate(&_RoninValidatorSet.TransactOpts, _number) } -// SubmitBlockReward is a paid mutator transaction binding the contract method 0x52091f17. +// SetMaxValidatorNumber is a paid mutator transaction binding the contract method 0x823a7b9c. // -// Solidity: function submitBlockReward() payable returns() -func (_RoninValidatorSet *RoninValidatorSetTransactor) SubmitBlockReward(opts *bind.TransactOpts) (*types.Transaction, error) { - return _RoninValidatorSet.contract.Transact(opts, "submitBlockReward") +// Solidity: function setMaxValidatorNumber(uint256 __maxValidatorNumber) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactor) SetMaxValidatorNumber(opts *bind.TransactOpts, __maxValidatorNumber *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.contract.Transact(opts, "setMaxValidatorNumber", __maxValidatorNumber) } -// SubmitBlockReward is a paid mutator transaction binding the contract method 0x52091f17. +// SetMaxValidatorNumber is a paid mutator transaction binding the contract method 0x823a7b9c. // -// Solidity: function submitBlockReward() payable returns() -func (_RoninValidatorSet *RoninValidatorSetSession) SubmitBlockReward() (*types.Transaction, error) { - return _RoninValidatorSet.Contract.SubmitBlockReward(&_RoninValidatorSet.TransactOpts) +// Solidity: function setMaxValidatorNumber(uint256 __maxValidatorNumber) returns() +func (_RoninValidatorSet *RoninValidatorSetSession) SetMaxValidatorNumber(__maxValidatorNumber *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SetMaxValidatorNumber(&_RoninValidatorSet.TransactOpts, __maxValidatorNumber) } -// SubmitBlockReward is a paid mutator transaction binding the contract method 0x52091f17. +// SetMaxValidatorNumber is a paid mutator transaction binding the contract method 0x823a7b9c. // -// Solidity: function submitBlockReward() payable returns() -func (_RoninValidatorSet *RoninValidatorSetTransactorSession) SubmitBlockReward() (*types.Transaction, error) { - return _RoninValidatorSet.Contract.SubmitBlockReward(&_RoninValidatorSet.TransactOpts) +// Solidity: function setMaxValidatorNumber(uint256 __maxValidatorNumber) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) SetMaxValidatorNumber(__maxValidatorNumber *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SetMaxValidatorNumber(&_RoninValidatorSet.TransactOpts, __maxValidatorNumber) } -// WrapUpEpoch is a paid mutator transaction binding the contract method 0x72e46810. +// SetNumberOfBlocksInEpoch is a paid mutator transaction binding the contract method 0xd72733fc. // -// Solidity: function wrapUpEpoch() payable returns() -func (_RoninValidatorSet *RoninValidatorSetTransactor) WrapUpEpoch(opts *bind.TransactOpts) (*types.Transaction, error) { - return _RoninValidatorSet.contract.Transact(opts, "wrapUpEpoch") +// Solidity: function setNumberOfBlocksInEpoch(uint256 __numberOfBlocksInEpoch) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactor) SetNumberOfBlocksInEpoch(opts *bind.TransactOpts, __numberOfBlocksInEpoch *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.contract.Transact(opts, "setNumberOfBlocksInEpoch", __numberOfBlocksInEpoch) } -// WrapUpEpoch is a paid mutator transaction binding the contract method 0x72e46810. +// SetNumberOfBlocksInEpoch is a paid mutator transaction binding the contract method 0xd72733fc. // -// Solidity: function wrapUpEpoch() payable returns() -func (_RoninValidatorSet *RoninValidatorSetSession) WrapUpEpoch() (*types.Transaction, error) { - return _RoninValidatorSet.Contract.WrapUpEpoch(&_RoninValidatorSet.TransactOpts) +// Solidity: function setNumberOfBlocksInEpoch(uint256 __numberOfBlocksInEpoch) returns() +func (_RoninValidatorSet *RoninValidatorSetSession) SetNumberOfBlocksInEpoch(__numberOfBlocksInEpoch *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SetNumberOfBlocksInEpoch(&_RoninValidatorSet.TransactOpts, __numberOfBlocksInEpoch) } -// WrapUpEpoch is a paid mutator transaction binding the contract method 0x72e46810. +// SetNumberOfBlocksInEpoch is a paid mutator transaction binding the contract method 0xd72733fc. // -// Solidity: function wrapUpEpoch() payable returns() -func (_RoninValidatorSet *RoninValidatorSetTransactorSession) WrapUpEpoch() (*types.Transaction, error) { - return _RoninValidatorSet.Contract.WrapUpEpoch(&_RoninValidatorSet.TransactOpts) +// Solidity: function setNumberOfBlocksInEpoch(uint256 __numberOfBlocksInEpoch) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) SetNumberOfBlocksInEpoch(__numberOfBlocksInEpoch *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SetNumberOfBlocksInEpoch(&_RoninValidatorSet.TransactOpts, __numberOfBlocksInEpoch) } -// RoninValidatorSetInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the RoninValidatorSet contract. -type RoninValidatorSetInitializedIterator struct { - Event *RoninValidatorSetInitialized // Event containing the contract specifics and raw log +// SetNumberOfEpochsInPeriod is a paid mutator transaction binding the contract method 0xd6fa322c. +// +// Solidity: function setNumberOfEpochsInPeriod(uint256 __numberOfEpochsInPeriod) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactor) SetNumberOfEpochsInPeriod(opts *bind.TransactOpts, __numberOfEpochsInPeriod *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.contract.Transact(opts, "setNumberOfEpochsInPeriod", __numberOfEpochsInPeriod) +} - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data +// SetNumberOfEpochsInPeriod is a paid mutator transaction binding the contract method 0xd6fa322c. +// +// Solidity: function setNumberOfEpochsInPeriod(uint256 __numberOfEpochsInPeriod) returns() +func (_RoninValidatorSet *RoninValidatorSetSession) SetNumberOfEpochsInPeriod(__numberOfEpochsInPeriod *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SetNumberOfEpochsInPeriod(&_RoninValidatorSet.TransactOpts, __numberOfEpochsInPeriod) +} - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration +// SetNumberOfEpochsInPeriod is a paid mutator transaction binding the contract method 0xd6fa322c. +// +// Solidity: function setNumberOfEpochsInPeriod(uint256 __numberOfEpochsInPeriod) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) SetNumberOfEpochsInPeriod(__numberOfEpochsInPeriod *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SetNumberOfEpochsInPeriod(&_RoninValidatorSet.TransactOpts, __numberOfEpochsInPeriod) } -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *RoninValidatorSetInitializedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(RoninValidatorSetInitialized) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false +// SetPrioritizedAddresses is a paid mutator transaction binding the contract method 0xd33a5ca2. +// +// Solidity: function setPrioritizedAddresses(address[] _addrs, bool[] _statuses) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactor) SetPrioritizedAddresses(opts *bind.TransactOpts, _addrs []common.Address, _statuses []bool) (*types.Transaction, error) { + return _RoninValidatorSet.contract.Transact(opts, "setPrioritizedAddresses", _addrs, _statuses) +} + +// SetPrioritizedAddresses is a paid mutator transaction binding the contract method 0xd33a5ca2. +// +// Solidity: function setPrioritizedAddresses(address[] _addrs, bool[] _statuses) returns() +func (_RoninValidatorSet *RoninValidatorSetSession) SetPrioritizedAddresses(_addrs []common.Address, _statuses []bool) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SetPrioritizedAddresses(&_RoninValidatorSet.TransactOpts, _addrs, _statuses) +} + +// SetPrioritizedAddresses is a paid mutator transaction binding the contract method 0xd33a5ca2. +// +// Solidity: function setPrioritizedAddresses(address[] _addrs, bool[] _statuses) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) SetPrioritizedAddresses(_addrs []common.Address, _statuses []bool) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SetPrioritizedAddresses(&_RoninValidatorSet.TransactOpts, _addrs, _statuses) +} + +// SetSlashIndicatorContract is a paid mutator transaction binding the contract method 0x2bcf3d15. +// +// Solidity: function setSlashIndicatorContract(address _addr) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactor) SetSlashIndicatorContract(opts *bind.TransactOpts, _addr common.Address) (*types.Transaction, error) { + return _RoninValidatorSet.contract.Transact(opts, "setSlashIndicatorContract", _addr) +} + +// SetSlashIndicatorContract is a paid mutator transaction binding the contract method 0x2bcf3d15. +// +// Solidity: function setSlashIndicatorContract(address _addr) returns() +func (_RoninValidatorSet *RoninValidatorSetSession) SetSlashIndicatorContract(_addr common.Address) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SetSlashIndicatorContract(&_RoninValidatorSet.TransactOpts, _addr) +} + +// SetSlashIndicatorContract is a paid mutator transaction binding the contract method 0x2bcf3d15. +// +// Solidity: function setSlashIndicatorContract(address _addr) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) SetSlashIndicatorContract(_addr common.Address) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SetSlashIndicatorContract(&_RoninValidatorSet.TransactOpts, _addr) +} + +// SetStakingContract is a paid mutator transaction binding the contract method 0x9dd373b9. +// +// Solidity: function setStakingContract(address _addr) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactor) SetStakingContract(opts *bind.TransactOpts, _addr common.Address) (*types.Transaction, error) { + return _RoninValidatorSet.contract.Transact(opts, "setStakingContract", _addr) +} + +// SetStakingContract is a paid mutator transaction binding the contract method 0x9dd373b9. +// +// Solidity: function setStakingContract(address _addr) returns() +func (_RoninValidatorSet *RoninValidatorSetSession) SetStakingContract(_addr common.Address) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SetStakingContract(&_RoninValidatorSet.TransactOpts, _addr) +} + +// SetStakingContract is a paid mutator transaction binding the contract method 0x9dd373b9. +// +// Solidity: function setStakingContract(address _addr) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) SetStakingContract(_addr common.Address) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SetStakingContract(&_RoninValidatorSet.TransactOpts, _addr) +} + +// SetStakingVestingContract is a paid mutator transaction binding the contract method 0xad295783. +// +// Solidity: function setStakingVestingContract(address _addr) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactor) SetStakingVestingContract(opts *bind.TransactOpts, _addr common.Address) (*types.Transaction, error) { + return _RoninValidatorSet.contract.Transact(opts, "setStakingVestingContract", _addr) +} + +// SetStakingVestingContract is a paid mutator transaction binding the contract method 0xad295783. +// +// Solidity: function setStakingVestingContract(address _addr) returns() +func (_RoninValidatorSet *RoninValidatorSetSession) SetStakingVestingContract(_addr common.Address) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SetStakingVestingContract(&_RoninValidatorSet.TransactOpts, _addr) +} + +// SetStakingVestingContract is a paid mutator transaction binding the contract method 0xad295783. +// +// Solidity: function setStakingVestingContract(address _addr) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) SetStakingVestingContract(_addr common.Address) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SetStakingVestingContract(&_RoninValidatorSet.TransactOpts, _addr) +} + +// Slash is a paid mutator transaction binding the contract method 0x70f81f6c. +// +// Solidity: function slash(address _validatorAddr, uint256 _newJailedUntil, uint256 _slashAmount) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactor) Slash(opts *bind.TransactOpts, _validatorAddr common.Address, _newJailedUntil *big.Int, _slashAmount *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.contract.Transact(opts, "slash", _validatorAddr, _newJailedUntil, _slashAmount) +} + +// Slash is a paid mutator transaction binding the contract method 0x70f81f6c. +// +// Solidity: function slash(address _validatorAddr, uint256 _newJailedUntil, uint256 _slashAmount) returns() +func (_RoninValidatorSet *RoninValidatorSetSession) Slash(_validatorAddr common.Address, _newJailedUntil *big.Int, _slashAmount *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.Slash(&_RoninValidatorSet.TransactOpts, _validatorAddr, _newJailedUntil, _slashAmount) +} + +// Slash is a paid mutator transaction binding the contract method 0x70f81f6c. +// +// Solidity: function slash(address _validatorAddr, uint256 _newJailedUntil, uint256 _slashAmount) returns() +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) Slash(_validatorAddr common.Address, _newJailedUntil *big.Int, _slashAmount *big.Int) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.Slash(&_RoninValidatorSet.TransactOpts, _validatorAddr, _newJailedUntil, _slashAmount) +} + +// SubmitBlockReward is a paid mutator transaction binding the contract method 0x52091f17. +// +// Solidity: function submitBlockReward() payable returns() +func (_RoninValidatorSet *RoninValidatorSetTransactor) SubmitBlockReward(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RoninValidatorSet.contract.Transact(opts, "submitBlockReward") +} + +// SubmitBlockReward is a paid mutator transaction binding the contract method 0x52091f17. +// +// Solidity: function submitBlockReward() payable returns() +func (_RoninValidatorSet *RoninValidatorSetSession) SubmitBlockReward() (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SubmitBlockReward(&_RoninValidatorSet.TransactOpts) +} + +// SubmitBlockReward is a paid mutator transaction binding the contract method 0x52091f17. +// +// Solidity: function submitBlockReward() payable returns() +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) SubmitBlockReward() (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SubmitBlockReward(&_RoninValidatorSet.TransactOpts) +} + +// SyncCandidates is a paid mutator transaction binding the contract method 0xde7702fb. +// +// Solidity: function syncCandidates() returns(uint256[] _balances) +func (_RoninValidatorSet *RoninValidatorSetTransactor) SyncCandidates(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RoninValidatorSet.contract.Transact(opts, "syncCandidates") +} + +// SyncCandidates is a paid mutator transaction binding the contract method 0xde7702fb. +// +// Solidity: function syncCandidates() returns(uint256[] _balances) +func (_RoninValidatorSet *RoninValidatorSetSession) SyncCandidates() (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SyncCandidates(&_RoninValidatorSet.TransactOpts) +} + +// SyncCandidates is a paid mutator transaction binding the contract method 0xde7702fb. +// +// Solidity: function syncCandidates() returns(uint256[] _balances) +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) SyncCandidates() (*types.Transaction, error) { + return _RoninValidatorSet.Contract.SyncCandidates(&_RoninValidatorSet.TransactOpts) +} + +// WrapUpEpoch is a paid mutator transaction binding the contract method 0x72e46810. +// +// Solidity: function wrapUpEpoch() payable returns() +func (_RoninValidatorSet *RoninValidatorSetTransactor) WrapUpEpoch(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RoninValidatorSet.contract.Transact(opts, "wrapUpEpoch") +} + +// WrapUpEpoch is a paid mutator transaction binding the contract method 0x72e46810. +// +// Solidity: function wrapUpEpoch() payable returns() +func (_RoninValidatorSet *RoninValidatorSetSession) WrapUpEpoch() (*types.Transaction, error) { + return _RoninValidatorSet.Contract.WrapUpEpoch(&_RoninValidatorSet.TransactOpts) +} + +// WrapUpEpoch is a paid mutator transaction binding the contract method 0x72e46810. +// +// Solidity: function wrapUpEpoch() payable returns() +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) WrapUpEpoch() (*types.Transaction, error) { + return _RoninValidatorSet.Contract.WrapUpEpoch(&_RoninValidatorSet.TransactOpts) +} + +// Fallback is a paid mutator transaction binding the contract fallback function. +// +// Solidity: fallback() payable returns() +func (_RoninValidatorSet *RoninValidatorSetTransactor) Fallback(opts *bind.TransactOpts, calldata []byte) (*types.Transaction, error) { + return _RoninValidatorSet.contract.RawTransact(opts, calldata) +} + +// Fallback is a paid mutator transaction binding the contract fallback function. +// +// Solidity: fallback() payable returns() +func (_RoninValidatorSet *RoninValidatorSetSession) Fallback(calldata []byte) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.Fallback(&_RoninValidatorSet.TransactOpts, calldata) +} + +// Fallback is a paid mutator transaction binding the contract fallback function. +// +// Solidity: fallback() payable returns() +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) Fallback(calldata []byte) (*types.Transaction, error) { + return _RoninValidatorSet.Contract.Fallback(&_RoninValidatorSet.TransactOpts, calldata) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_RoninValidatorSet *RoninValidatorSetTransactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RoninValidatorSet.contract.RawTransact(opts, nil) // calldata is disallowed for receive function +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_RoninValidatorSet *RoninValidatorSetSession) Receive() (*types.Transaction, error) { + return _RoninValidatorSet.Contract.Receive(&_RoninValidatorSet.TransactOpts) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_RoninValidatorSet *RoninValidatorSetTransactorSession) Receive() (*types.Transaction, error) { + return _RoninValidatorSet.Contract.Receive(&_RoninValidatorSet.TransactOpts) +} + +// RoninValidatorSetAddressesPriorityStatusUpdatedIterator is returned from FilterAddressesPriorityStatusUpdated and is used to iterate over the raw logs and unpacked data for AddressesPriorityStatusUpdated events raised by the RoninValidatorSet contract. +type RoninValidatorSetAddressesPriorityStatusUpdatedIterator struct { + Event *RoninValidatorSetAddressesPriorityStatusUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RoninValidatorSetAddressesPriorityStatusUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetAddressesPriorityStatusUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetAddressesPriorityStatusUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RoninValidatorSetAddressesPriorityStatusUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RoninValidatorSetAddressesPriorityStatusUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RoninValidatorSetAddressesPriorityStatusUpdated represents a AddressesPriorityStatusUpdated event raised by the RoninValidatorSet contract. +type RoninValidatorSetAddressesPriorityStatusUpdated struct { + Arg0 []common.Address + Arg1 []bool + Raw types.Log // Blockchain specific contextual infos +} + +// FilterAddressesPriorityStatusUpdated is a free log retrieval operation binding the contract event 0xa52c766fffd3af2ed65a8599973f96a0713c68566068cc057ad25cabd88ed466. +// +// Solidity: event AddressesPriorityStatusUpdated(address[] arg0, bool[] arg1) +func (_RoninValidatorSet *RoninValidatorSetFilterer) FilterAddressesPriorityStatusUpdated(opts *bind.FilterOpts) (*RoninValidatorSetAddressesPriorityStatusUpdatedIterator, error) { + + logs, sub, err := _RoninValidatorSet.contract.FilterLogs(opts, "AddressesPriorityStatusUpdated") + if err != nil { + return nil, err + } + return &RoninValidatorSetAddressesPriorityStatusUpdatedIterator{contract: _RoninValidatorSet.contract, event: "AddressesPriorityStatusUpdated", logs: logs, sub: sub}, nil +} + +// WatchAddressesPriorityStatusUpdated is a free log subscription operation binding the contract event 0xa52c766fffd3af2ed65a8599973f96a0713c68566068cc057ad25cabd88ed466. +// +// Solidity: event AddressesPriorityStatusUpdated(address[] arg0, bool[] arg1) +func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchAddressesPriorityStatusUpdated(opts *bind.WatchOpts, sink chan<- *RoninValidatorSetAddressesPriorityStatusUpdated) (event.Subscription, error) { + + logs, sub, err := _RoninValidatorSet.contract.WatchLogs(opts, "AddressesPriorityStatusUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RoninValidatorSetAddressesPriorityStatusUpdated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "AddressesPriorityStatusUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseAddressesPriorityStatusUpdated is a log parse operation binding the contract event 0xa52c766fffd3af2ed65a8599973f96a0713c68566068cc057ad25cabd88ed466. +// +// Solidity: event AddressesPriorityStatusUpdated(address[] arg0, bool[] arg1) +func (_RoninValidatorSet *RoninValidatorSetFilterer) ParseAddressesPriorityStatusUpdated(log types.Log) (*RoninValidatorSetAddressesPriorityStatusUpdated, error) { + event := new(RoninValidatorSetAddressesPriorityStatusUpdated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "AddressesPriorityStatusUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RoninValidatorSetBlockRewardSubmittedIterator is returned from FilterBlockRewardSubmitted and is used to iterate over the raw logs and unpacked data for BlockRewardSubmitted events raised by the RoninValidatorSet contract. +type RoninValidatorSetBlockRewardSubmittedIterator struct { + Event *RoninValidatorSetBlockRewardSubmitted // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RoninValidatorSetBlockRewardSubmittedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetBlockRewardSubmitted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetBlockRewardSubmitted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RoninValidatorSetBlockRewardSubmittedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RoninValidatorSetBlockRewardSubmittedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RoninValidatorSetBlockRewardSubmitted represents a BlockRewardSubmitted event raised by the RoninValidatorSet contract. +type RoninValidatorSetBlockRewardSubmitted struct { + CoinbaseAddr common.Address + SubmittedAmount *big.Int + BonusAmount *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterBlockRewardSubmitted is a free log retrieval operation binding the contract event 0x0ede5c3be8625943fa64003cd4b91230089411249f3059bac6500873543ca9b1. +// +// Solidity: event BlockRewardSubmitted(address coinbaseAddr, uint256 submittedAmount, uint256 bonusAmount) +func (_RoninValidatorSet *RoninValidatorSetFilterer) FilterBlockRewardSubmitted(opts *bind.FilterOpts) (*RoninValidatorSetBlockRewardSubmittedIterator, error) { + + logs, sub, err := _RoninValidatorSet.contract.FilterLogs(opts, "BlockRewardSubmitted") + if err != nil { + return nil, err + } + return &RoninValidatorSetBlockRewardSubmittedIterator{contract: _RoninValidatorSet.contract, event: "BlockRewardSubmitted", logs: logs, sub: sub}, nil +} + +// WatchBlockRewardSubmitted is a free log subscription operation binding the contract event 0x0ede5c3be8625943fa64003cd4b91230089411249f3059bac6500873543ca9b1. +// +// Solidity: event BlockRewardSubmitted(address coinbaseAddr, uint256 submittedAmount, uint256 bonusAmount) +func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchBlockRewardSubmitted(opts *bind.WatchOpts, sink chan<- *RoninValidatorSetBlockRewardSubmitted) (event.Subscription, error) { + + logs, sub, err := _RoninValidatorSet.contract.WatchLogs(opts, "BlockRewardSubmitted") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RoninValidatorSetBlockRewardSubmitted) + if err := _RoninValidatorSet.contract.UnpackLog(event, "BlockRewardSubmitted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseBlockRewardSubmitted is a log parse operation binding the contract event 0x0ede5c3be8625943fa64003cd4b91230089411249f3059bac6500873543ca9b1. +// +// Solidity: event BlockRewardSubmitted(address coinbaseAddr, uint256 submittedAmount, uint256 bonusAmount) +func (_RoninValidatorSet *RoninValidatorSetFilterer) ParseBlockRewardSubmitted(log types.Log) (*RoninValidatorSetBlockRewardSubmitted, error) { + event := new(RoninValidatorSetBlockRewardSubmitted) + if err := _RoninValidatorSet.contract.UnpackLog(event, "BlockRewardSubmitted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RoninValidatorSetInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the RoninValidatorSet contract. +type RoninValidatorSetInitializedIterator struct { + Event *RoninValidatorSetInitialized // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RoninValidatorSetInitializedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetInitialized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetInitialized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RoninValidatorSetInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RoninValidatorSetInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RoninValidatorSetInitialized represents a Initialized event raised by the RoninValidatorSet contract. +type RoninValidatorSetInitialized struct { + Version uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_RoninValidatorSet *RoninValidatorSetFilterer) FilterInitialized(opts *bind.FilterOpts) (*RoninValidatorSetInitializedIterator, error) { + + logs, sub, err := _RoninValidatorSet.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &RoninValidatorSetInitializedIterator{contract: _RoninValidatorSet.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *RoninValidatorSetInitialized) (event.Subscription, error) { + + logs, sub, err := _RoninValidatorSet.contract.WatchLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RoninValidatorSetInitialized) + if err := _RoninValidatorSet.contract.UnpackLog(event, "Initialized", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseInitialized is a log parse operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_RoninValidatorSet *RoninValidatorSetFilterer) ParseInitialized(log types.Log) (*RoninValidatorSetInitialized, error) { + event := new(RoninValidatorSetInitialized) + if err := _RoninValidatorSet.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RoninValidatorSetMaintenanceContractUpdatedIterator is returned from FilterMaintenanceContractUpdated and is used to iterate over the raw logs and unpacked data for MaintenanceContractUpdated events raised by the RoninValidatorSet contract. +type RoninValidatorSetMaintenanceContractUpdatedIterator struct { + Event *RoninValidatorSetMaintenanceContractUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RoninValidatorSetMaintenanceContractUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetMaintenanceContractUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetMaintenanceContractUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RoninValidatorSetMaintenanceContractUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RoninValidatorSetMaintenanceContractUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RoninValidatorSetMaintenanceContractUpdated represents a MaintenanceContractUpdated event raised by the RoninValidatorSet contract. +type RoninValidatorSetMaintenanceContractUpdated struct { + Arg0 common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterMaintenanceContractUpdated is a free log retrieval operation binding the contract event 0x31a33f126a5bae3c5bdf6cfc2cd6dcfffe2fe9634bdb09e21c44762993889e3b. +// +// Solidity: event MaintenanceContractUpdated(address arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) FilterMaintenanceContractUpdated(opts *bind.FilterOpts) (*RoninValidatorSetMaintenanceContractUpdatedIterator, error) { + + logs, sub, err := _RoninValidatorSet.contract.FilterLogs(opts, "MaintenanceContractUpdated") + if err != nil { + return nil, err + } + return &RoninValidatorSetMaintenanceContractUpdatedIterator{contract: _RoninValidatorSet.contract, event: "MaintenanceContractUpdated", logs: logs, sub: sub}, nil +} + +// WatchMaintenanceContractUpdated is a free log subscription operation binding the contract event 0x31a33f126a5bae3c5bdf6cfc2cd6dcfffe2fe9634bdb09e21c44762993889e3b. +// +// Solidity: event MaintenanceContractUpdated(address arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchMaintenanceContractUpdated(opts *bind.WatchOpts, sink chan<- *RoninValidatorSetMaintenanceContractUpdated) (event.Subscription, error) { + + logs, sub, err := _RoninValidatorSet.contract.WatchLogs(opts, "MaintenanceContractUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RoninValidatorSetMaintenanceContractUpdated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "MaintenanceContractUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseMaintenanceContractUpdated is a log parse operation binding the contract event 0x31a33f126a5bae3c5bdf6cfc2cd6dcfffe2fe9634bdb09e21c44762993889e3b. +// +// Solidity: event MaintenanceContractUpdated(address arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) ParseMaintenanceContractUpdated(log types.Log) (*RoninValidatorSetMaintenanceContractUpdated, error) { + event := new(RoninValidatorSetMaintenanceContractUpdated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "MaintenanceContractUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RoninValidatorSetMaxPrioritizedValidatorNumberUpdatedIterator is returned from FilterMaxPrioritizedValidatorNumberUpdated and is used to iterate over the raw logs and unpacked data for MaxPrioritizedValidatorNumberUpdated events raised by the RoninValidatorSet contract. +type RoninValidatorSetMaxPrioritizedValidatorNumberUpdatedIterator struct { + Event *RoninValidatorSetMaxPrioritizedValidatorNumberUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RoninValidatorSetMaxPrioritizedValidatorNumberUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetMaxPrioritizedValidatorNumberUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetMaxPrioritizedValidatorNumberUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RoninValidatorSetMaxPrioritizedValidatorNumberUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RoninValidatorSetMaxPrioritizedValidatorNumberUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RoninValidatorSetMaxPrioritizedValidatorNumberUpdated represents a MaxPrioritizedValidatorNumberUpdated event raised by the RoninValidatorSet contract. +type RoninValidatorSetMaxPrioritizedValidatorNumberUpdated struct { + Arg0 *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterMaxPrioritizedValidatorNumberUpdated is a free log retrieval operation binding the contract event 0xa9588dc77416849bd922605ce4fc806712281ad8a8f32d4238d6c8cca548e15e. +// +// Solidity: event MaxPrioritizedValidatorNumberUpdated(uint256 arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) FilterMaxPrioritizedValidatorNumberUpdated(opts *bind.FilterOpts) (*RoninValidatorSetMaxPrioritizedValidatorNumberUpdatedIterator, error) { + + logs, sub, err := _RoninValidatorSet.contract.FilterLogs(opts, "MaxPrioritizedValidatorNumberUpdated") + if err != nil { + return nil, err + } + return &RoninValidatorSetMaxPrioritizedValidatorNumberUpdatedIterator{contract: _RoninValidatorSet.contract, event: "MaxPrioritizedValidatorNumberUpdated", logs: logs, sub: sub}, nil +} + +// WatchMaxPrioritizedValidatorNumberUpdated is a free log subscription operation binding the contract event 0xa9588dc77416849bd922605ce4fc806712281ad8a8f32d4238d6c8cca548e15e. +// +// Solidity: event MaxPrioritizedValidatorNumberUpdated(uint256 arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchMaxPrioritizedValidatorNumberUpdated(opts *bind.WatchOpts, sink chan<- *RoninValidatorSetMaxPrioritizedValidatorNumberUpdated) (event.Subscription, error) { + + logs, sub, err := _RoninValidatorSet.contract.WatchLogs(opts, "MaxPrioritizedValidatorNumberUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RoninValidatorSetMaxPrioritizedValidatorNumberUpdated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "MaxPrioritizedValidatorNumberUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseMaxPrioritizedValidatorNumberUpdated is a log parse operation binding the contract event 0xa9588dc77416849bd922605ce4fc806712281ad8a8f32d4238d6c8cca548e15e. +// +// Solidity: event MaxPrioritizedValidatorNumberUpdated(uint256 arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) ParseMaxPrioritizedValidatorNumberUpdated(log types.Log) (*RoninValidatorSetMaxPrioritizedValidatorNumberUpdated, error) { + event := new(RoninValidatorSetMaxPrioritizedValidatorNumberUpdated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "MaxPrioritizedValidatorNumberUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RoninValidatorSetMaxValidatorCandidateUpdatedIterator is returned from FilterMaxValidatorCandidateUpdated and is used to iterate over the raw logs and unpacked data for MaxValidatorCandidateUpdated events raised by the RoninValidatorSet contract. +type RoninValidatorSetMaxValidatorCandidateUpdatedIterator struct { + Event *RoninValidatorSetMaxValidatorCandidateUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RoninValidatorSetMaxValidatorCandidateUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetMaxValidatorCandidateUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetMaxValidatorCandidateUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RoninValidatorSetMaxValidatorCandidateUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RoninValidatorSetMaxValidatorCandidateUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RoninValidatorSetMaxValidatorCandidateUpdated represents a MaxValidatorCandidateUpdated event raised by the RoninValidatorSet contract. +type RoninValidatorSetMaxValidatorCandidateUpdated struct { + Threshold *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterMaxValidatorCandidateUpdated is a free log retrieval operation binding the contract event 0x82d5dc32d1b741512ad09c32404d7e7921e8934c6222343d95f55f7a2b9b2ab4. +// +// Solidity: event MaxValidatorCandidateUpdated(uint256 threshold) +func (_RoninValidatorSet *RoninValidatorSetFilterer) FilterMaxValidatorCandidateUpdated(opts *bind.FilterOpts) (*RoninValidatorSetMaxValidatorCandidateUpdatedIterator, error) { + + logs, sub, err := _RoninValidatorSet.contract.FilterLogs(opts, "MaxValidatorCandidateUpdated") + if err != nil { + return nil, err + } + return &RoninValidatorSetMaxValidatorCandidateUpdatedIterator{contract: _RoninValidatorSet.contract, event: "MaxValidatorCandidateUpdated", logs: logs, sub: sub}, nil +} + +// WatchMaxValidatorCandidateUpdated is a free log subscription operation binding the contract event 0x82d5dc32d1b741512ad09c32404d7e7921e8934c6222343d95f55f7a2b9b2ab4. +// +// Solidity: event MaxValidatorCandidateUpdated(uint256 threshold) +func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchMaxValidatorCandidateUpdated(opts *bind.WatchOpts, sink chan<- *RoninValidatorSetMaxValidatorCandidateUpdated) (event.Subscription, error) { + + logs, sub, err := _RoninValidatorSet.contract.WatchLogs(opts, "MaxValidatorCandidateUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RoninValidatorSetMaxValidatorCandidateUpdated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "MaxValidatorCandidateUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseMaxValidatorCandidateUpdated is a log parse operation binding the contract event 0x82d5dc32d1b741512ad09c32404d7e7921e8934c6222343d95f55f7a2b9b2ab4. +// +// Solidity: event MaxValidatorCandidateUpdated(uint256 threshold) +func (_RoninValidatorSet *RoninValidatorSetFilterer) ParseMaxValidatorCandidateUpdated(log types.Log) (*RoninValidatorSetMaxValidatorCandidateUpdated, error) { + event := new(RoninValidatorSetMaxValidatorCandidateUpdated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "MaxValidatorCandidateUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RoninValidatorSetMaxValidatorNumberUpdatedIterator is returned from FilterMaxValidatorNumberUpdated and is used to iterate over the raw logs and unpacked data for MaxValidatorNumberUpdated events raised by the RoninValidatorSet contract. +type RoninValidatorSetMaxValidatorNumberUpdatedIterator struct { + Event *RoninValidatorSetMaxValidatorNumberUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RoninValidatorSetMaxValidatorNumberUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetMaxValidatorNumberUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetMaxValidatorNumberUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RoninValidatorSetMaxValidatorNumberUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RoninValidatorSetMaxValidatorNumberUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RoninValidatorSetMaxValidatorNumberUpdated represents a MaxValidatorNumberUpdated event raised by the RoninValidatorSet contract. +type RoninValidatorSetMaxValidatorNumberUpdated struct { + Arg0 *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterMaxValidatorNumberUpdated is a free log retrieval operation binding the contract event 0xb5464c05fd0e0f000c535850116cda2742ee1f7b34384cb920ad7b8e802138b5. +// +// Solidity: event MaxValidatorNumberUpdated(uint256 arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) FilterMaxValidatorNumberUpdated(opts *bind.FilterOpts) (*RoninValidatorSetMaxValidatorNumberUpdatedIterator, error) { + + logs, sub, err := _RoninValidatorSet.contract.FilterLogs(opts, "MaxValidatorNumberUpdated") + if err != nil { + return nil, err + } + return &RoninValidatorSetMaxValidatorNumberUpdatedIterator{contract: _RoninValidatorSet.contract, event: "MaxValidatorNumberUpdated", logs: logs, sub: sub}, nil +} + +// WatchMaxValidatorNumberUpdated is a free log subscription operation binding the contract event 0xb5464c05fd0e0f000c535850116cda2742ee1f7b34384cb920ad7b8e802138b5. +// +// Solidity: event MaxValidatorNumberUpdated(uint256 arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchMaxValidatorNumberUpdated(opts *bind.WatchOpts, sink chan<- *RoninValidatorSetMaxValidatorNumberUpdated) (event.Subscription, error) { + + logs, sub, err := _RoninValidatorSet.contract.WatchLogs(opts, "MaxValidatorNumberUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RoninValidatorSetMaxValidatorNumberUpdated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "MaxValidatorNumberUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseMaxValidatorNumberUpdated is a log parse operation binding the contract event 0xb5464c05fd0e0f000c535850116cda2742ee1f7b34384cb920ad7b8e802138b5. +// +// Solidity: event MaxValidatorNumberUpdated(uint256 arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) ParseMaxValidatorNumberUpdated(log types.Log) (*RoninValidatorSetMaxValidatorNumberUpdated, error) { + event := new(RoninValidatorSetMaxValidatorNumberUpdated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "MaxValidatorNumberUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RoninValidatorSetMiningRewardDistributedIterator is returned from FilterMiningRewardDistributed and is used to iterate over the raw logs and unpacked data for MiningRewardDistributed events raised by the RoninValidatorSet contract. +type RoninValidatorSetMiningRewardDistributedIterator struct { + Event *RoninValidatorSetMiningRewardDistributed // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RoninValidatorSetMiningRewardDistributedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetMiningRewardDistributed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetMiningRewardDistributed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RoninValidatorSetMiningRewardDistributedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RoninValidatorSetMiningRewardDistributedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RoninValidatorSetMiningRewardDistributed represents a MiningRewardDistributed event raised by the RoninValidatorSet contract. +type RoninValidatorSetMiningRewardDistributed struct { + ValidatorAddr common.Address + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterMiningRewardDistributed is a free log retrieval operation binding the contract event 0x9bae506d1374d366cdfa60105473d52dfdbaaae60e55de77bf6ee07f2add0cfb. +// +// Solidity: event MiningRewardDistributed(address validatorAddr, uint256 amount) +func (_RoninValidatorSet *RoninValidatorSetFilterer) FilterMiningRewardDistributed(opts *bind.FilterOpts) (*RoninValidatorSetMiningRewardDistributedIterator, error) { + + logs, sub, err := _RoninValidatorSet.contract.FilterLogs(opts, "MiningRewardDistributed") + if err != nil { + return nil, err + } + return &RoninValidatorSetMiningRewardDistributedIterator{contract: _RoninValidatorSet.contract, event: "MiningRewardDistributed", logs: logs, sub: sub}, nil +} + +// WatchMiningRewardDistributed is a free log subscription operation binding the contract event 0x9bae506d1374d366cdfa60105473d52dfdbaaae60e55de77bf6ee07f2add0cfb. +// +// Solidity: event MiningRewardDistributed(address validatorAddr, uint256 amount) +func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchMiningRewardDistributed(opts *bind.WatchOpts, sink chan<- *RoninValidatorSetMiningRewardDistributed) (event.Subscription, error) { + + logs, sub, err := _RoninValidatorSet.contract.WatchLogs(opts, "MiningRewardDistributed") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RoninValidatorSetMiningRewardDistributed) + if err := _RoninValidatorSet.contract.UnpackLog(event, "MiningRewardDistributed", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseMiningRewardDistributed is a log parse operation binding the contract event 0x9bae506d1374d366cdfa60105473d52dfdbaaae60e55de77bf6ee07f2add0cfb. +// +// Solidity: event MiningRewardDistributed(address validatorAddr, uint256 amount) +func (_RoninValidatorSet *RoninValidatorSetFilterer) ParseMiningRewardDistributed(log types.Log) (*RoninValidatorSetMiningRewardDistributed, error) { + event := new(RoninValidatorSetMiningRewardDistributed) + if err := _RoninValidatorSet.contract.UnpackLog(event, "MiningRewardDistributed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RoninValidatorSetNumberOfBlocksInEpochUpdatedIterator is returned from FilterNumberOfBlocksInEpochUpdated and is used to iterate over the raw logs and unpacked data for NumberOfBlocksInEpochUpdated events raised by the RoninValidatorSet contract. +type RoninValidatorSetNumberOfBlocksInEpochUpdatedIterator struct { + Event *RoninValidatorSetNumberOfBlocksInEpochUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RoninValidatorSetNumberOfBlocksInEpochUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetNumberOfBlocksInEpochUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetNumberOfBlocksInEpochUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RoninValidatorSetNumberOfBlocksInEpochUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RoninValidatorSetNumberOfBlocksInEpochUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RoninValidatorSetNumberOfBlocksInEpochUpdated represents a NumberOfBlocksInEpochUpdated event raised by the RoninValidatorSet contract. +type RoninValidatorSetNumberOfBlocksInEpochUpdated struct { + Arg0 *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterNumberOfBlocksInEpochUpdated is a free log retrieval operation binding the contract event 0xbfd285a38b782d8a00e424fb824320ff3d1a698534358d02da611468d59b7808. +// +// Solidity: event NumberOfBlocksInEpochUpdated(uint256 arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) FilterNumberOfBlocksInEpochUpdated(opts *bind.FilterOpts) (*RoninValidatorSetNumberOfBlocksInEpochUpdatedIterator, error) { + + logs, sub, err := _RoninValidatorSet.contract.FilterLogs(opts, "NumberOfBlocksInEpochUpdated") + if err != nil { + return nil, err + } + return &RoninValidatorSetNumberOfBlocksInEpochUpdatedIterator{contract: _RoninValidatorSet.contract, event: "NumberOfBlocksInEpochUpdated", logs: logs, sub: sub}, nil +} + +// WatchNumberOfBlocksInEpochUpdated is a free log subscription operation binding the contract event 0xbfd285a38b782d8a00e424fb824320ff3d1a698534358d02da611468d59b7808. +// +// Solidity: event NumberOfBlocksInEpochUpdated(uint256 arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchNumberOfBlocksInEpochUpdated(opts *bind.WatchOpts, sink chan<- *RoninValidatorSetNumberOfBlocksInEpochUpdated) (event.Subscription, error) { + + logs, sub, err := _RoninValidatorSet.contract.WatchLogs(opts, "NumberOfBlocksInEpochUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RoninValidatorSetNumberOfBlocksInEpochUpdated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "NumberOfBlocksInEpochUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseNumberOfBlocksInEpochUpdated is a log parse operation binding the contract event 0xbfd285a38b782d8a00e424fb824320ff3d1a698534358d02da611468d59b7808. +// +// Solidity: event NumberOfBlocksInEpochUpdated(uint256 arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) ParseNumberOfBlocksInEpochUpdated(log types.Log) (*RoninValidatorSetNumberOfBlocksInEpochUpdated, error) { + event := new(RoninValidatorSetNumberOfBlocksInEpochUpdated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "NumberOfBlocksInEpochUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RoninValidatorSetNumberOfEpochsInPeriodUpdatedIterator is returned from FilterNumberOfEpochsInPeriodUpdated and is used to iterate over the raw logs and unpacked data for NumberOfEpochsInPeriodUpdated events raised by the RoninValidatorSet contract. +type RoninValidatorSetNumberOfEpochsInPeriodUpdatedIterator struct { + Event *RoninValidatorSetNumberOfEpochsInPeriodUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RoninValidatorSetNumberOfEpochsInPeriodUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetNumberOfEpochsInPeriodUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetNumberOfEpochsInPeriodUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RoninValidatorSetNumberOfEpochsInPeriodUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RoninValidatorSetNumberOfEpochsInPeriodUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RoninValidatorSetNumberOfEpochsInPeriodUpdated represents a NumberOfEpochsInPeriodUpdated event raised by the RoninValidatorSet contract. +type RoninValidatorSetNumberOfEpochsInPeriodUpdated struct { + Arg0 *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterNumberOfEpochsInPeriodUpdated is a free log retrieval operation binding the contract event 0x1d01baa2db15fced4f4e5fcfd4245e65ad9b083c110d26542f4a5f78d5425e77. +// +// Solidity: event NumberOfEpochsInPeriodUpdated(uint256 arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) FilterNumberOfEpochsInPeriodUpdated(opts *bind.FilterOpts) (*RoninValidatorSetNumberOfEpochsInPeriodUpdatedIterator, error) { + + logs, sub, err := _RoninValidatorSet.contract.FilterLogs(opts, "NumberOfEpochsInPeriodUpdated") + if err != nil { + return nil, err + } + return &RoninValidatorSetNumberOfEpochsInPeriodUpdatedIterator{contract: _RoninValidatorSet.contract, event: "NumberOfEpochsInPeriodUpdated", logs: logs, sub: sub}, nil +} + +// WatchNumberOfEpochsInPeriodUpdated is a free log subscription operation binding the contract event 0x1d01baa2db15fced4f4e5fcfd4245e65ad9b083c110d26542f4a5f78d5425e77. +// +// Solidity: event NumberOfEpochsInPeriodUpdated(uint256 arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchNumberOfEpochsInPeriodUpdated(opts *bind.WatchOpts, sink chan<- *RoninValidatorSetNumberOfEpochsInPeriodUpdated) (event.Subscription, error) { + + logs, sub, err := _RoninValidatorSet.contract.WatchLogs(opts, "NumberOfEpochsInPeriodUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RoninValidatorSetNumberOfEpochsInPeriodUpdated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "NumberOfEpochsInPeriodUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseNumberOfEpochsInPeriodUpdated is a log parse operation binding the contract event 0x1d01baa2db15fced4f4e5fcfd4245e65ad9b083c110d26542f4a5f78d5425e77. +// +// Solidity: event NumberOfEpochsInPeriodUpdated(uint256 arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) ParseNumberOfEpochsInPeriodUpdated(log types.Log) (*RoninValidatorSetNumberOfEpochsInPeriodUpdated, error) { + event := new(RoninValidatorSetNumberOfEpochsInPeriodUpdated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "NumberOfEpochsInPeriodUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RoninValidatorSetRewardDeprecatedIterator is returned from FilterRewardDeprecated and is used to iterate over the raw logs and unpacked data for RewardDeprecated events raised by the RoninValidatorSet contract. +type RoninValidatorSetRewardDeprecatedIterator struct { + Event *RoninValidatorSetRewardDeprecated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RoninValidatorSetRewardDeprecatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetRewardDeprecated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetRewardDeprecated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RoninValidatorSetRewardDeprecatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RoninValidatorSetRewardDeprecatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RoninValidatorSetRewardDeprecated represents a RewardDeprecated event raised by the RoninValidatorSet contract. +type RoninValidatorSetRewardDeprecated struct { + CoinbaseAddr common.Address + RewardAmount *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRewardDeprecated is a free log retrieval operation binding the contract event 0x2439a6ac441f1d6b3dbb7827ef6e056822e2261f900cad468012eee4f1f7f31c. +// +// Solidity: event RewardDeprecated(address coinbaseAddr, uint256 rewardAmount) +func (_RoninValidatorSet *RoninValidatorSetFilterer) FilterRewardDeprecated(opts *bind.FilterOpts) (*RoninValidatorSetRewardDeprecatedIterator, error) { + + logs, sub, err := _RoninValidatorSet.contract.FilterLogs(opts, "RewardDeprecated") + if err != nil { + return nil, err + } + return &RoninValidatorSetRewardDeprecatedIterator{contract: _RoninValidatorSet.contract, event: "RewardDeprecated", logs: logs, sub: sub}, nil +} + +// WatchRewardDeprecated is a free log subscription operation binding the contract event 0x2439a6ac441f1d6b3dbb7827ef6e056822e2261f900cad468012eee4f1f7f31c. +// +// Solidity: event RewardDeprecated(address coinbaseAddr, uint256 rewardAmount) +func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchRewardDeprecated(opts *bind.WatchOpts, sink chan<- *RoninValidatorSetRewardDeprecated) (event.Subscription, error) { + + logs, sub, err := _RoninValidatorSet.contract.WatchLogs(opts, "RewardDeprecated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RoninValidatorSetRewardDeprecated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "RewardDeprecated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseRewardDeprecated is a log parse operation binding the contract event 0x2439a6ac441f1d6b3dbb7827ef6e056822e2261f900cad468012eee4f1f7f31c. +// +// Solidity: event RewardDeprecated(address coinbaseAddr, uint256 rewardAmount) +func (_RoninValidatorSet *RoninValidatorSetFilterer) ParseRewardDeprecated(log types.Log) (*RoninValidatorSetRewardDeprecated, error) { + event := new(RoninValidatorSetRewardDeprecated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "RewardDeprecated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RoninValidatorSetSlashIndicatorContractUpdatedIterator is returned from FilterSlashIndicatorContractUpdated and is used to iterate over the raw logs and unpacked data for SlashIndicatorContractUpdated events raised by the RoninValidatorSet contract. +type RoninValidatorSetSlashIndicatorContractUpdatedIterator struct { + Event *RoninValidatorSetSlashIndicatorContractUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RoninValidatorSetSlashIndicatorContractUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetSlashIndicatorContractUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetSlashIndicatorContractUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RoninValidatorSetSlashIndicatorContractUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RoninValidatorSetSlashIndicatorContractUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RoninValidatorSetSlashIndicatorContractUpdated represents a SlashIndicatorContractUpdated event raised by the RoninValidatorSet contract. +type RoninValidatorSetSlashIndicatorContractUpdated struct { + Arg0 common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterSlashIndicatorContractUpdated is a free log retrieval operation binding the contract event 0xaa5b07dd43aa44c69b70a6a2b9c3fcfed12b6e5f6323596ba7ac91035ab80a4f. +// +// Solidity: event SlashIndicatorContractUpdated(address arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) FilterSlashIndicatorContractUpdated(opts *bind.FilterOpts) (*RoninValidatorSetSlashIndicatorContractUpdatedIterator, error) { + + logs, sub, err := _RoninValidatorSet.contract.FilterLogs(opts, "SlashIndicatorContractUpdated") + if err != nil { + return nil, err + } + return &RoninValidatorSetSlashIndicatorContractUpdatedIterator{contract: _RoninValidatorSet.contract, event: "SlashIndicatorContractUpdated", logs: logs, sub: sub}, nil +} + +// WatchSlashIndicatorContractUpdated is a free log subscription operation binding the contract event 0xaa5b07dd43aa44c69b70a6a2b9c3fcfed12b6e5f6323596ba7ac91035ab80a4f. +// +// Solidity: event SlashIndicatorContractUpdated(address arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchSlashIndicatorContractUpdated(opts *bind.WatchOpts, sink chan<- *RoninValidatorSetSlashIndicatorContractUpdated) (event.Subscription, error) { + + logs, sub, err := _RoninValidatorSet.contract.WatchLogs(opts, "SlashIndicatorContractUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RoninValidatorSetSlashIndicatorContractUpdated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "SlashIndicatorContractUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseSlashIndicatorContractUpdated is a log parse operation binding the contract event 0xaa5b07dd43aa44c69b70a6a2b9c3fcfed12b6e5f6323596ba7ac91035ab80a4f. +// +// Solidity: event SlashIndicatorContractUpdated(address arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) ParseSlashIndicatorContractUpdated(log types.Log) (*RoninValidatorSetSlashIndicatorContractUpdated, error) { + event := new(RoninValidatorSetSlashIndicatorContractUpdated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "SlashIndicatorContractUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RoninValidatorSetStakingContractUpdatedIterator is returned from FilterStakingContractUpdated and is used to iterate over the raw logs and unpacked data for StakingContractUpdated events raised by the RoninValidatorSet contract. +type RoninValidatorSetStakingContractUpdatedIterator struct { + Event *RoninValidatorSetStakingContractUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RoninValidatorSetStakingContractUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetStakingContractUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetStakingContractUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RoninValidatorSetStakingContractUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RoninValidatorSetStakingContractUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RoninValidatorSetStakingContractUpdated represents a StakingContractUpdated event raised by the RoninValidatorSet contract. +type RoninValidatorSetStakingContractUpdated struct { + Arg0 common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterStakingContractUpdated is a free log retrieval operation binding the contract event 0x6397f5b135542bb3f477cb346cfab5abdec1251d08dc8f8d4efb4ffe122ea0bf. +// +// Solidity: event StakingContractUpdated(address arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) FilterStakingContractUpdated(opts *bind.FilterOpts) (*RoninValidatorSetStakingContractUpdatedIterator, error) { + + logs, sub, err := _RoninValidatorSet.contract.FilterLogs(opts, "StakingContractUpdated") + if err != nil { + return nil, err + } + return &RoninValidatorSetStakingContractUpdatedIterator{contract: _RoninValidatorSet.contract, event: "StakingContractUpdated", logs: logs, sub: sub}, nil +} + +// WatchStakingContractUpdated is a free log subscription operation binding the contract event 0x6397f5b135542bb3f477cb346cfab5abdec1251d08dc8f8d4efb4ffe122ea0bf. +// +// Solidity: event StakingContractUpdated(address arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchStakingContractUpdated(opts *bind.WatchOpts, sink chan<- *RoninValidatorSetStakingContractUpdated) (event.Subscription, error) { + + logs, sub, err := _RoninValidatorSet.contract.WatchLogs(opts, "StakingContractUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RoninValidatorSetStakingContractUpdated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "StakingContractUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseStakingContractUpdated is a log parse operation binding the contract event 0x6397f5b135542bb3f477cb346cfab5abdec1251d08dc8f8d4efb4ffe122ea0bf. +// +// Solidity: event StakingContractUpdated(address arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) ParseStakingContractUpdated(log types.Log) (*RoninValidatorSetStakingContractUpdated, error) { + event := new(RoninValidatorSetStakingContractUpdated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "StakingContractUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RoninValidatorSetStakingRewardDistributedIterator is returned from FilterStakingRewardDistributed and is used to iterate over the raw logs and unpacked data for StakingRewardDistributed events raised by the RoninValidatorSet contract. +type RoninValidatorSetStakingRewardDistributedIterator struct { + Event *RoninValidatorSetStakingRewardDistributed // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RoninValidatorSetStakingRewardDistributedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetStakingRewardDistributed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetStakingRewardDistributed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RoninValidatorSetStakingRewardDistributedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RoninValidatorSetStakingRewardDistributedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RoninValidatorSetStakingRewardDistributed represents a StakingRewardDistributed event raised by the RoninValidatorSet contract. +type RoninValidatorSetStakingRewardDistributed struct { + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterStakingRewardDistributed is a free log retrieval operation binding the contract event 0xeb09b8cc1cefa77cd4ec30003e6364cf60afcedd20be8c09f26e717788baf139. +// +// Solidity: event StakingRewardDistributed(uint256 amount) +func (_RoninValidatorSet *RoninValidatorSetFilterer) FilterStakingRewardDistributed(opts *bind.FilterOpts) (*RoninValidatorSetStakingRewardDistributedIterator, error) { + + logs, sub, err := _RoninValidatorSet.contract.FilterLogs(opts, "StakingRewardDistributed") + if err != nil { + return nil, err + } + return &RoninValidatorSetStakingRewardDistributedIterator{contract: _RoninValidatorSet.contract, event: "StakingRewardDistributed", logs: logs, sub: sub}, nil +} + +// WatchStakingRewardDistributed is a free log subscription operation binding the contract event 0xeb09b8cc1cefa77cd4ec30003e6364cf60afcedd20be8c09f26e717788baf139. +// +// Solidity: event StakingRewardDistributed(uint256 amount) +func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchStakingRewardDistributed(opts *bind.WatchOpts, sink chan<- *RoninValidatorSetStakingRewardDistributed) (event.Subscription, error) { + + logs, sub, err := _RoninValidatorSet.contract.WatchLogs(opts, "StakingRewardDistributed") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RoninValidatorSetStakingRewardDistributed) + if err := _RoninValidatorSet.contract.UnpackLog(event, "StakingRewardDistributed", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseStakingRewardDistributed is a log parse operation binding the contract event 0xeb09b8cc1cefa77cd4ec30003e6364cf60afcedd20be8c09f26e717788baf139. +// +// Solidity: event StakingRewardDistributed(uint256 amount) +func (_RoninValidatorSet *RoninValidatorSetFilterer) ParseStakingRewardDistributed(log types.Log) (*RoninValidatorSetStakingRewardDistributed, error) { + event := new(RoninValidatorSetStakingRewardDistributed) + if err := _RoninValidatorSet.contract.UnpackLog(event, "StakingRewardDistributed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RoninValidatorSetStakingVestingContractUpdatedIterator is returned from FilterStakingVestingContractUpdated and is used to iterate over the raw logs and unpacked data for StakingVestingContractUpdated events raised by the RoninValidatorSet contract. +type RoninValidatorSetStakingVestingContractUpdatedIterator struct { + Event *RoninValidatorSetStakingVestingContractUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RoninValidatorSetStakingVestingContractUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetStakingVestingContractUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetStakingVestingContractUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RoninValidatorSetStakingVestingContractUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RoninValidatorSetStakingVestingContractUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RoninValidatorSetStakingVestingContractUpdated represents a StakingVestingContractUpdated event raised by the RoninValidatorSet contract. +type RoninValidatorSetStakingVestingContractUpdated struct { + Arg0 common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterStakingVestingContractUpdated is a free log retrieval operation binding the contract event 0xc328090a37d855191ab58469296f98f87a851ca57d5cdfd1e9ac3c83e9e7096d. +// +// Solidity: event StakingVestingContractUpdated(address arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) FilterStakingVestingContractUpdated(opts *bind.FilterOpts) (*RoninValidatorSetStakingVestingContractUpdatedIterator, error) { + + logs, sub, err := _RoninValidatorSet.contract.FilterLogs(opts, "StakingVestingContractUpdated") + if err != nil { + return nil, err + } + return &RoninValidatorSetStakingVestingContractUpdatedIterator{contract: _RoninValidatorSet.contract, event: "StakingVestingContractUpdated", logs: logs, sub: sub}, nil +} + +// WatchStakingVestingContractUpdated is a free log subscription operation binding the contract event 0xc328090a37d855191ab58469296f98f87a851ca57d5cdfd1e9ac3c83e9e7096d. +// +// Solidity: event StakingVestingContractUpdated(address arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchStakingVestingContractUpdated(opts *bind.WatchOpts, sink chan<- *RoninValidatorSetStakingVestingContractUpdated) (event.Subscription, error) { + + logs, sub, err := _RoninValidatorSet.contract.WatchLogs(opts, "StakingVestingContractUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RoninValidatorSetStakingVestingContractUpdated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "StakingVestingContractUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseStakingVestingContractUpdated is a log parse operation binding the contract event 0xc328090a37d855191ab58469296f98f87a851ca57d5cdfd1e9ac3c83e9e7096d. +// +// Solidity: event StakingVestingContractUpdated(address arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) ParseStakingVestingContractUpdated(log types.Log) (*RoninValidatorSetStakingVestingContractUpdated, error) { + event := new(RoninValidatorSetStakingVestingContractUpdated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "StakingVestingContractUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RoninValidatorSetValidatorCandidateAddedIterator is returned from FilterValidatorCandidateAdded and is used to iterate over the raw logs and unpacked data for ValidatorCandidateAdded events raised by the RoninValidatorSet contract. +type RoninValidatorSetValidatorCandidateAddedIterator struct { + Event *RoninValidatorSetValidatorCandidateAdded // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RoninValidatorSetValidatorCandidateAddedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetValidatorCandidateAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetValidatorCandidateAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RoninValidatorSetValidatorCandidateAddedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RoninValidatorSetValidatorCandidateAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RoninValidatorSetValidatorCandidateAdded represents a ValidatorCandidateAdded event raised by the RoninValidatorSet contract. +type RoninValidatorSetValidatorCandidateAdded struct { + ConsensusAddr common.Address + TreasuryAddr common.Address + CandidateIdx *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterValidatorCandidateAdded is a free log retrieval operation binding the contract event 0x5ea0ccc37694ce2ce1e44e06663c8caff77c1ec661d991e2ece3a6195f879acf. +// +// Solidity: event ValidatorCandidateAdded(address indexed consensusAddr, address indexed treasuryAddr, uint256 indexed candidateIdx) +func (_RoninValidatorSet *RoninValidatorSetFilterer) FilterValidatorCandidateAdded(opts *bind.FilterOpts, consensusAddr []common.Address, treasuryAddr []common.Address, candidateIdx []*big.Int) (*RoninValidatorSetValidatorCandidateAddedIterator, error) { + + var consensusAddrRule []interface{} + for _, consensusAddrItem := range consensusAddr { + consensusAddrRule = append(consensusAddrRule, consensusAddrItem) + } + var treasuryAddrRule []interface{} + for _, treasuryAddrItem := range treasuryAddr { + treasuryAddrRule = append(treasuryAddrRule, treasuryAddrItem) + } + var candidateIdxRule []interface{} + for _, candidateIdxItem := range candidateIdx { + candidateIdxRule = append(candidateIdxRule, candidateIdxItem) + } + + logs, sub, err := _RoninValidatorSet.contract.FilterLogs(opts, "ValidatorCandidateAdded", consensusAddrRule, treasuryAddrRule, candidateIdxRule) + if err != nil { + return nil, err + } + return &RoninValidatorSetValidatorCandidateAddedIterator{contract: _RoninValidatorSet.contract, event: "ValidatorCandidateAdded", logs: logs, sub: sub}, nil +} + +// WatchValidatorCandidateAdded is a free log subscription operation binding the contract event 0x5ea0ccc37694ce2ce1e44e06663c8caff77c1ec661d991e2ece3a6195f879acf. +// +// Solidity: event ValidatorCandidateAdded(address indexed consensusAddr, address indexed treasuryAddr, uint256 indexed candidateIdx) +func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchValidatorCandidateAdded(opts *bind.WatchOpts, sink chan<- *RoninValidatorSetValidatorCandidateAdded, consensusAddr []common.Address, treasuryAddr []common.Address, candidateIdx []*big.Int) (event.Subscription, error) { + + var consensusAddrRule []interface{} + for _, consensusAddrItem := range consensusAddr { + consensusAddrRule = append(consensusAddrRule, consensusAddrItem) + } + var treasuryAddrRule []interface{} + for _, treasuryAddrItem := range treasuryAddr { + treasuryAddrRule = append(treasuryAddrRule, treasuryAddrItem) + } + var candidateIdxRule []interface{} + for _, candidateIdxItem := range candidateIdx { + candidateIdxRule = append(candidateIdxRule, candidateIdxItem) + } + + logs, sub, err := _RoninValidatorSet.contract.WatchLogs(opts, "ValidatorCandidateAdded", consensusAddrRule, treasuryAddrRule, candidateIdxRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RoninValidatorSetValidatorCandidateAdded) + if err := _RoninValidatorSet.contract.UnpackLog(event, "ValidatorCandidateAdded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseValidatorCandidateAdded is a log parse operation binding the contract event 0x5ea0ccc37694ce2ce1e44e06663c8caff77c1ec661d991e2ece3a6195f879acf. +// +// Solidity: event ValidatorCandidateAdded(address indexed consensusAddr, address indexed treasuryAddr, uint256 indexed candidateIdx) +func (_RoninValidatorSet *RoninValidatorSetFilterer) ParseValidatorCandidateAdded(log types.Log) (*RoninValidatorSetValidatorCandidateAdded, error) { + event := new(RoninValidatorSetValidatorCandidateAdded) + if err := _RoninValidatorSet.contract.UnpackLog(event, "ValidatorCandidateAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RoninValidatorSetValidatorCandidateRemovedIterator is returned from FilterValidatorCandidateRemoved and is used to iterate over the raw logs and unpacked data for ValidatorCandidateRemoved events raised by the RoninValidatorSet contract. +type RoninValidatorSetValidatorCandidateRemovedIterator struct { + Event *RoninValidatorSetValidatorCandidateRemoved // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RoninValidatorSetValidatorCandidateRemovedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetValidatorCandidateRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false } it.Event.Raw = log return true @@ -863,7 +3528,7 @@ func (it *RoninValidatorSetInitializedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(RoninValidatorSetInitialized) + it.Event = new(RoninValidatorSetValidatorCandidateRemoved) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -879,41 +3544,51 @@ func (it *RoninValidatorSetInitializedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *RoninValidatorSetInitializedIterator) Error() error { +func (it *RoninValidatorSetValidatorCandidateRemovedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *RoninValidatorSetInitializedIterator) Close() error { +func (it *RoninValidatorSetValidatorCandidateRemovedIterator) Close() error { it.sub.Unsubscribe() return nil } -// RoninValidatorSetInitialized represents a Initialized event raised by the RoninValidatorSet contract. -type RoninValidatorSetInitialized struct { - Version uint8 - Raw types.Log // Blockchain specific contextual infos +// RoninValidatorSetValidatorCandidateRemoved represents a ValidatorCandidateRemoved event raised by the RoninValidatorSet contract. +type RoninValidatorSetValidatorCandidateRemoved struct { + ConsensusAddr common.Address + Raw types.Log // Blockchain specific contextual infos } -// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// FilterValidatorCandidateRemoved is a free log retrieval operation binding the contract event 0xec1ae6fd172c65ee5804ae3dafed7d57ec0f1e1183f910a8b7bd4abe31110f15. // -// Solidity: event Initialized(uint8 version) -func (_RoninValidatorSet *RoninValidatorSetFilterer) FilterInitialized(opts *bind.FilterOpts) (*RoninValidatorSetInitializedIterator, error) { +// Solidity: event ValidatorCandidateRemoved(address indexed consensusAddr) +func (_RoninValidatorSet *RoninValidatorSetFilterer) FilterValidatorCandidateRemoved(opts *bind.FilterOpts, consensusAddr []common.Address) (*RoninValidatorSetValidatorCandidateRemovedIterator, error) { - logs, sub, err := _RoninValidatorSet.contract.FilterLogs(opts, "Initialized") + var consensusAddrRule []interface{} + for _, consensusAddrItem := range consensusAddr { + consensusAddrRule = append(consensusAddrRule, consensusAddrItem) + } + + logs, sub, err := _RoninValidatorSet.contract.FilterLogs(opts, "ValidatorCandidateRemoved", consensusAddrRule) if err != nil { return nil, err } - return &RoninValidatorSetInitializedIterator{contract: _RoninValidatorSet.contract, event: "Initialized", logs: logs, sub: sub}, nil + return &RoninValidatorSetValidatorCandidateRemovedIterator{contract: _RoninValidatorSet.contract, event: "ValidatorCandidateRemoved", logs: logs, sub: sub}, nil } -// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// WatchValidatorCandidateRemoved is a free log subscription operation binding the contract event 0xec1ae6fd172c65ee5804ae3dafed7d57ec0f1e1183f910a8b7bd4abe31110f15. // -// Solidity: event Initialized(uint8 version) -func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *RoninValidatorSetInitialized) (event.Subscription, error) { +// Solidity: event ValidatorCandidateRemoved(address indexed consensusAddr) +func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchValidatorCandidateRemoved(opts *bind.WatchOpts, sink chan<- *RoninValidatorSetValidatorCandidateRemoved, consensusAddr []common.Address) (event.Subscription, error) { - logs, sub, err := _RoninValidatorSet.contract.WatchLogs(opts, "Initialized") + var consensusAddrRule []interface{} + for _, consensusAddrItem := range consensusAddr { + consensusAddrRule = append(consensusAddrRule, consensusAddrItem) + } + + logs, sub, err := _RoninValidatorSet.contract.WatchLogs(opts, "ValidatorCandidateRemoved", consensusAddrRule) if err != nil { return nil, err } @@ -923,8 +3598,8 @@ func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchInitialized(opts *bind select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(RoninValidatorSetInitialized) - if err := _RoninValidatorSet.contract.UnpackLog(event, "Initialized", log); err != nil { + event := new(RoninValidatorSetValidatorCandidateRemoved) + if err := _RoninValidatorSet.contract.UnpackLog(event, "ValidatorCandidateRemoved", log); err != nil { return err } event.Raw = log @@ -945,12 +3620,282 @@ func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchInitialized(opts *bind }), nil } -// ParseInitialized is a log parse operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// ParseValidatorCandidateRemoved is a log parse operation binding the contract event 0xec1ae6fd172c65ee5804ae3dafed7d57ec0f1e1183f910a8b7bd4abe31110f15. // -// Solidity: event Initialized(uint8 version) -func (_RoninValidatorSet *RoninValidatorSetFilterer) ParseInitialized(log types.Log) (*RoninValidatorSetInitialized, error) { - event := new(RoninValidatorSetInitialized) - if err := _RoninValidatorSet.contract.UnpackLog(event, "Initialized", log); err != nil { +// Solidity: event ValidatorCandidateRemoved(address indexed consensusAddr) +func (_RoninValidatorSet *RoninValidatorSetFilterer) ParseValidatorCandidateRemoved(log types.Log) (*RoninValidatorSetValidatorCandidateRemoved, error) { + event := new(RoninValidatorSetValidatorCandidateRemoved) + if err := _RoninValidatorSet.contract.UnpackLog(event, "ValidatorCandidateRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RoninValidatorSetValidatorPunishedIterator is returned from FilterValidatorPunished and is used to iterate over the raw logs and unpacked data for ValidatorPunished events raised by the RoninValidatorSet contract. +type RoninValidatorSetValidatorPunishedIterator struct { + Event *RoninValidatorSetValidatorPunished // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RoninValidatorSetValidatorPunishedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetValidatorPunished) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetValidatorPunished) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RoninValidatorSetValidatorPunishedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RoninValidatorSetValidatorPunishedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RoninValidatorSetValidatorPunished represents a ValidatorPunished event raised by the RoninValidatorSet contract. +type RoninValidatorSetValidatorPunished struct { + ValidatorAddr common.Address + JailedUntil *big.Int + DeductedStakingAmount *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterValidatorPunished is a free log retrieval operation binding the contract event 0x69284547cc931ff0e04d5a21cdfb0748f22a3788269711028ce1d4833900e474. +// +// Solidity: event ValidatorPunished(address validatorAddr, uint256 jailedUntil, uint256 deductedStakingAmount) +func (_RoninValidatorSet *RoninValidatorSetFilterer) FilterValidatorPunished(opts *bind.FilterOpts) (*RoninValidatorSetValidatorPunishedIterator, error) { + + logs, sub, err := _RoninValidatorSet.contract.FilterLogs(opts, "ValidatorPunished") + if err != nil { + return nil, err + } + return &RoninValidatorSetValidatorPunishedIterator{contract: _RoninValidatorSet.contract, event: "ValidatorPunished", logs: logs, sub: sub}, nil +} + +// WatchValidatorPunished is a free log subscription operation binding the contract event 0x69284547cc931ff0e04d5a21cdfb0748f22a3788269711028ce1d4833900e474. +// +// Solidity: event ValidatorPunished(address validatorAddr, uint256 jailedUntil, uint256 deductedStakingAmount) +func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchValidatorPunished(opts *bind.WatchOpts, sink chan<- *RoninValidatorSetValidatorPunished) (event.Subscription, error) { + + logs, sub, err := _RoninValidatorSet.contract.WatchLogs(opts, "ValidatorPunished") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RoninValidatorSetValidatorPunished) + if err := _RoninValidatorSet.contract.UnpackLog(event, "ValidatorPunished", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseValidatorPunished is a log parse operation binding the contract event 0x69284547cc931ff0e04d5a21cdfb0748f22a3788269711028ce1d4833900e474. +// +// Solidity: event ValidatorPunished(address validatorAddr, uint256 jailedUntil, uint256 deductedStakingAmount) +func (_RoninValidatorSet *RoninValidatorSetFilterer) ParseValidatorPunished(log types.Log) (*RoninValidatorSetValidatorPunished, error) { + event := new(RoninValidatorSetValidatorPunished) + if err := _RoninValidatorSet.contract.UnpackLog(event, "ValidatorPunished", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// RoninValidatorSetValidatorSetUpdatedIterator is returned from FilterValidatorSetUpdated and is used to iterate over the raw logs and unpacked data for ValidatorSetUpdated events raised by the RoninValidatorSet contract. +type RoninValidatorSetValidatorSetUpdatedIterator struct { + Event *RoninValidatorSetValidatorSetUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *RoninValidatorSetValidatorSetUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetValidatorSetUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(RoninValidatorSetValidatorSetUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *RoninValidatorSetValidatorSetUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *RoninValidatorSetValidatorSetUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// RoninValidatorSetValidatorSetUpdated represents a ValidatorSetUpdated event raised by the RoninValidatorSet contract. +type RoninValidatorSetValidatorSetUpdated struct { + Arg0 []common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterValidatorSetUpdated is a free log retrieval operation binding the contract event 0x6120448f3d4245c1ff708d970c34e1b6484ee22a794ede0bfca2317a97aa8ced. +// +// Solidity: event ValidatorSetUpdated(address[] arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) FilterValidatorSetUpdated(opts *bind.FilterOpts) (*RoninValidatorSetValidatorSetUpdatedIterator, error) { + + logs, sub, err := _RoninValidatorSet.contract.FilterLogs(opts, "ValidatorSetUpdated") + if err != nil { + return nil, err + } + return &RoninValidatorSetValidatorSetUpdatedIterator{contract: _RoninValidatorSet.contract, event: "ValidatorSetUpdated", logs: logs, sub: sub}, nil +} + +// WatchValidatorSetUpdated is a free log subscription operation binding the contract event 0x6120448f3d4245c1ff708d970c34e1b6484ee22a794ede0bfca2317a97aa8ced. +// +// Solidity: event ValidatorSetUpdated(address[] arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) WatchValidatorSetUpdated(opts *bind.WatchOpts, sink chan<- *RoninValidatorSetValidatorSetUpdated) (event.Subscription, error) { + + logs, sub, err := _RoninValidatorSet.contract.WatchLogs(opts, "ValidatorSetUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(RoninValidatorSetValidatorSetUpdated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "ValidatorSetUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseValidatorSetUpdated is a log parse operation binding the contract event 0x6120448f3d4245c1ff708d970c34e1b6484ee22a794ede0bfca2317a97aa8ced. +// +// Solidity: event ValidatorSetUpdated(address[] arg0) +func (_RoninValidatorSet *RoninValidatorSetFilterer) ParseValidatorSetUpdated(log types.Log) (*RoninValidatorSetValidatorSetUpdated, error) { + event := new(RoninValidatorSetValidatorSetUpdated) + if err := _RoninValidatorSet.contract.UnpackLog(event, "ValidatorSetUpdated", log); err != nil { return nil, err } event.Raw = log diff --git a/consensus/consortium/generated_contracts/slash_indicator/slash_indicator.go b/consensus/consortium/generated_contracts/slash_indicator/slash_indicator.go index a40307adcc..96f0774366 100644 --- a/consensus/consortium/generated_contracts/slash_indicator/slash_indicator.go +++ b/consensus/consortium/generated_contracts/slash_indicator/slash_indicator.go @@ -30,8 +30,8 @@ var ( // SlashIndicatorMetaData contains all meta data concerning the SlashIndicator contract. var SlashIndicatorMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIRoninValidatorSet\",\"name\":\"_validatorSetContract\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"validators\",\"type\":\"address[]\"}],\"name\":\"UnavailabilityIndicatorsReset\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"validator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"enumISlashIndicator.SlashType\",\"name\":\"slashType\",\"type\":\"uint8\"}],\"name\":\"ValidatorSlashed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"felonyThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"validator\",\"type\":\"address\"}],\"name\":\"getSlashIndicator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSlashThresholds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastSlashedBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"misdemeanorThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_validatorAddrs\",\"type\":\"address[]\"}],\"name\":\"resetCounters\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validatorAddr\",\"type\":\"address\"}],\"name\":\"slash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_valAddr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_evidence\",\"type\":\"bytes\"}],\"name\":\"slashDoubleSign\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"validatorContract\",\"outputs\":[{\"internalType\":\"contractIRoninValidatorSet\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60806040523480156200001157600080fd5b506040516200104d3803806200104d83398181016040528101906200003791906200010d565b6032600281905550609660038190555080600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506200013f565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620000c18262000094565b9050919050565b6000620000d582620000b4565b9050919050565b620000e781620000c8565b8114620000f357600080fd5b50565b6000815190506200010781620000dc565b92915050565b6000602082840312156200012657620001256200008f565b5b60006200013684828501620000f6565b91505092915050565b610efe806200014f6000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c80638256ace6116100665780638256ace614610120578063994390891461013f578063aef250be1461015d578063c96be4cb1461017b578063ec35fe721461019757610093565b806337c8dab914610098578063389f4f71146100c8578063518e463a146100e6578063567a372d14610102575b600080fd5b6100b260048036038101906100ad91906107e0565b6101b3565b6040516100bf9190610826565b60405180910390f35b6100d06101fb565b6040516100dd9190610826565b60405180910390f35b61010060048036038101906100fb91906108a6565b610201565b005b61010a6102aa565b6040516101179190610826565b60405180910390f35b6101286102b0565b604051610136929190610906565b60405180910390f35b6101476102c1565b604051610154919061098e565b60405180910390f35b6101656102e7565b6040516101729190610826565b60405180910390f35b610195600480360381019061019091906107e0565b6102ed565b005b6101b160048036038101906101ac91906109ff565b610605565b005b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60035481565b4173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461026f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161026690610acf565b60405180910390fd5b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102a190610b3b565b60405180910390fd5b60025481565b600080600254600354915091509091565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015481565b4173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461035b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161035290610acf565b60405180910390fd5b600154431161039f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161039690610bcd565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1603156105fb5760008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000815461042090610c1c565b9190508190559050600354810361051257600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663722d298f836040518263ffffffff1660e01b815260040161048c9190610c73565b600060405180830381600087803b1580156104a657600080fd5b505af11580156104ba573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff167f72b4cbc6db714fd31d4f3a8686c34df7b11819178ea38a792798f38a99d15e4a60026040516105059190610d05565b60405180910390a26105f9565b60025481036105f857600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633dc56e09836040518263ffffffff1660e01b81526004016105769190610c73565b600060405180830381600087803b15801561059057600080fd5b505af11580156105a4573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff167f72b4cbc6db714fd31d4f3a8686c34df7b11819178ea38a792798f38a99d15e4a60016040516105ef9190610d05565b60405180910390a25b5b505b4360018190555050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610695576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90610d92565b60405180910390fd5b61069f82826106a3565b5050565b60008282905003156107745760005b82829050811015610739576000808484848181106106d3576106d2610db2565b5b90506020020160208101906106e891906107e0565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009055808061073190610c1c565b9150506106b2565b507f9ae71e4f83d6019cd988ca4c38a696d015d5f6e41f3fd708fb746d2b672b4996828260405161076b929190610ea4565b60405180910390a15b5050565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006107ad82610782565b9050919050565b6107bd816107a2565b81146107c857600080fd5b50565b6000813590506107da816107b4565b92915050565b6000602082840312156107f6576107f5610778565b5b6000610804848285016107cb565b91505092915050565b6000819050919050565b6108208161080d565b82525050565b600060208201905061083b6000830184610817565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261086657610865610841565b5b8235905067ffffffffffffffff81111561088357610882610846565b5b60208301915083600182028301111561089f5761089e61084b565b5b9250929050565b6000806000604084860312156108bf576108be610778565b5b60006108cd868287016107cb565b935050602084013567ffffffffffffffff8111156108ee576108ed61077d565b5b6108fa86828701610850565b92509250509250925092565b600060408201905061091b6000830185610817565b6109286020830184610817565b9392505050565b6000819050919050565b600061095461094f61094a84610782565b61092f565b610782565b9050919050565b600061096682610939565b9050919050565b60006109788261095b565b9050919050565b6109888161096d565b82525050565b60006020820190506109a3600083018461097f565b92915050565b60008083601f8401126109bf576109be610841565b5b8235905067ffffffffffffffff8111156109dc576109db610846565b5b6020830191508360208202830111156109f8576109f761084b565b5b9250929050565b60008060208385031215610a1657610a15610778565b5b600083013567ffffffffffffffff811115610a3457610a3361077d565b5b610a40858286016109a9565b92509250509250929050565b600082825260208201905092915050565b7f536c617368496e64696361746f723a206d6574686f642063616c6c657220697360008201527f206e6f742074686520636f696e62617365000000000000000000000000000000602082015250565b6000610ab9603183610a4c565b9150610ac482610a5d565b604082019050919050565b60006020820190508181036000830152610ae881610aac565b9050919050565b7f4e6f7420696d706c656d656e7465640000000000000000000000000000000000600082015250565b6000610b25600f83610a4c565b9150610b3082610aef565b602082019050919050565b60006020820190508181036000830152610b5481610b18565b9050919050565b7f536c617368496e64696361746f723a2063616e6e6f7420736c6173682074776960008201527f636520696e206f6e6520626c6f636b0000000000000000000000000000000000602082015250565b6000610bb7602f83610a4c565b9150610bc282610b5b565b604082019050919050565b60006020820190508181036000830152610be681610baa565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610c278261080d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610c5957610c58610bed565b5b600182019050919050565b610c6d816107a2565b82525050565b6000602082019050610c886000830184610c64565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110610cce57610ccd610c8e565b5b50565b6000819050610cdf82610cbd565b919050565b6000610cef82610cd1565b9050919050565b610cff81610ce4565b82525050565b6000602082019050610d1a6000830184610cf6565b92915050565b7f536c617368496e64696361746f723a206d6574686f642063616c6c657220697360008201527f206e6f74207468652076616c696461746f7220636f6e74726163740000000000602082015250565b6000610d7c603b83610a4c565b9150610d8782610d20565b604082019050919050565b60006020820190508181036000830152610dab81610d6f565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082825260208201905092915050565b6000819050919050565b610e05816107a2565b82525050565b6000610e178383610dfc565b60208301905092915050565b6000610e3260208401846107cb565b905092915050565b6000602082019050919050565b6000610e538385610de1565b9350610e5e82610df2565b8060005b85811015610e9757610e748284610e23565b610e7e8882610e0b565b9750610e8983610e3a565b925050600181019050610e62565b5085925050509392505050565b60006020820190508181036000830152610ebf818486610e47565b9050939250505056fea264697066735822122091242cd808a850e5ec6d87e9be207e3ce6e1d7f067c64bbea66e01a4beca6a7b64736f6c63430008100033", + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"felonyJailDuration\",\"type\":\"uint256\"}],\"name\":\"FelonyJailDurationUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"MaintenanceContractUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"slashDoubleSignAmount\",\"type\":\"uint256\"}],\"name\":\"SlashDoubleSignAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"slashFelonyAmount\",\"type\":\"uint256\"}],\"name\":\"SlashFelonyAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"felonyThreshold\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"misdemeanorThreshold\",\"type\":\"uint256\"}],\"name\":\"SlashThresholdsUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"validator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"enumISlashIndicator.SlashType\",\"name\":\"slashType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"period\",\"type\":\"uint256\"}],\"name\":\"UnavailabilitySlashed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"ValidatorContractUpdated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"currentUnavailabilityIndicator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"felonyJailDuration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"felonyThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validator\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_period\",\"type\":\"uint256\"}],\"name\":\"getUnavailabilityIndicator\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validatorAddr\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_period\",\"type\":\"uint256\"}],\"name\":\"getUnavailabilitySlashType\",\"outputs\":[{\"internalType\":\"enumISlashIndicator.SlashType\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getUnavailabilityThresholds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"__validatorContract\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"__maintenanceContract\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_misdemeanorThreshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_felonyThreshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_slashFelonyAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_slashDoubleSignAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_felonyJailBlocks\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastSlashedBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maintenanceContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"misdemeanorThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_felonyJailDuration\",\"type\":\"uint256\"}],\"name\":\"setFelonyJailDuration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"setMaintenanceContract\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_slashDoubleSignAmount\",\"type\":\"uint256\"}],\"name\":\"setSlashDoubleSignAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_slashFelonyAmount\",\"type\":\"uint256\"}],\"name\":\"setSlashFelonyAmount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_felonyThreshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_misdemeanorThreshold\",\"type\":\"uint256\"}],\"name\":\"setSlashThresholds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"setValidatorContract\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validatorAddr\",\"type\":\"address\"}],\"name\":\"slash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validatorAddr\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"slashDoubleSign\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"slashDoubleSignAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"slashFelonyAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"unavailabilityThresholdsOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"_misdemeanorThreshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_felonyThreshold\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"validatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60806040523480156200001157600080fd5b50620000226200002860201b60201c565b620001d6565b600160159054906101000a900460ff16156200007b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000729062000179565b60405180910390fd5b60ff8016600160149054906101000a900460ff1660ff161015620000f05760ff600160146101000a81548160ff021916908360ff1602179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249860ff604051620000e79190620001b9565b60405180910390a15b565b600082825260208201905092915050565b7f496e697469616c697a61626c653a20636f6e747261637420697320696e69746960008201527f616c697a696e6700000000000000000000000000000000000000000000000000602082015250565b600062000161602783620000f2565b91506200016e8262000103565b604082019050919050565b60006020820190508181036000830152620001948162000152565b9050919050565b600060ff82169050919050565b620001b3816200019b565b82525050565b6000602082019050620001d06000830184620001a8565b92915050565b61232680620001e66000396000f3fe608060405234801561001057600080fd5b50600436106101425760003560e01c806399439089116100b8578063d2cb215e1161007c578063d2cb215e14610364578063d919358714610382578063dfe484cb146103a1578063e4f9c4be146103bf578063edbf4ac2146103db578063f82bdd01146103f757610142565b806399439089146102c0578063aef250be146102de578063c96be4cb146102fc578063cdf64a7614610318578063d180ecb01461033457610142565b8063567a372d1161010a578063567a372d146101fe5780635786e9ee1461021c57806362ffe6cb146102385780636b79f95f146102685780636d14c4e5146102865780636e91bec5146102a457610142565b8063082e742014610147578063389f4f711461017757806346fe9311146101955780634d961e18146101b1578063518e463a146101e2575b600080fd5b610161600480360381019061015c9190611821565b610413565b60405161016e9190611867565b60405180910390f35b61017f6104bf565b60405161018c9190611867565b60405180910390f35b6101af60048036038101906101aa9190611821565b6104c5565b005b6101cb60048036038101906101c691906118ae565b610546565b6040516101d99291906118ee565b60405180910390f35b6101fc60048036038101906101f7919061197c565b610873565b005b6102066109a1565b6040516102139190611867565b60405180910390f35b610236600480360381019061023191906119dc565b6109a7565b005b610252600480360381019061024d91906118ae565b610a28565b60405161025f9190611867565b60405180910390f35b610270610a83565b60405161027d9190611867565b60405180910390f35b61028e610a89565b60405161029b9190611867565b60405180910390f35b6102be60048036038101906102b991906119dc565b610a8f565b005b6102c8610b10565b6040516102d59190611a18565b60405180910390f35b6102e6610b39565b6040516102f39190611867565b60405180910390f35b61031660048036038101906103119190611821565b610b3f565b005b610332600480360381019061032d9190611821565b611146565b005b61034e600480360381019061034991906118ae565b6111c7565b60405161035b9190611aaa565b60405180910390f35b61036c61122f565b6040516103799190611a18565b60405180910390f35b61038a611259565b6040516103989291906118ee565b60405180910390f35b6103a961126a565b6040516103b69190611867565b60405180910390f35b6103d960048036038101906103d49190611ac5565b611270565b005b6103f560048036038101906103f09190611b05565b6112f3565b005b610411600480360381019061040c91906119dc565b61146a565b005b60006104b88260008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f8549af9436040518263ffffffff1660e01b81526004016104729190611867565b602060405180830381865afa15801561048f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b39190611bbc565b610a28565b9050919050565b60065481565b6104cd6114eb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461053a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161053190611c6c565b60405180910390fd5b61054381611542565b50565b60008060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635186dc7e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105db9190611bbc565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636aa1c2ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610646573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066a9190611bbc565b6106749190611cbb565b905060008182866106859190611d44565b61068f9190611cbb565b90506000600183836106a19190611d75565b6106ab9190611da9565b90506000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d39fee34896040518263ffffffff1660e01b815260040161070a9190611a18565b606060405180830381865afa158015610727573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074b9190611ed2565b90506000610768848484600001516115bd9092919063ffffffff16565b90506000610785858585602001516115bd9092919063ffffffff16565b905060008690508280156107965750815b156107cd576001846000015185602001516107b19190611da9565b6107bb9190611d75565b816107c69190611da9565b9050610833565b82156108015760018460000151866107e59190611da9565b6107ef9190611d75565b816107fa9190611da9565b9050610832565b81156108315760018685602001516108199190611da9565b6108239190611d75565b8161082e9190611da9565b90505b5b5b61084a81886005546115d89092919063ffffffff16565b985061086381886006546115d89092919063ffffffff16565b9750505050505050509250929050565b4173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108d890611f71565b60405180910390fd5b6000801561099b5760008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370f81f6c857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6008546040518463ffffffff1660e01b815260040161096893929190611f91565b600060405180830381600087803b15801561098257600080fd5b505af1158015610996573d6000803e3d6000fd5b505050505b50505050565b60055481565b6109af6114eb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610a1c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a1390611c6c565b60405180910390fd5b610a25816115fa565b50565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b60095481565b60085481565b610a976114eb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b04576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610afb90611c6c565b60405180910390fd5b610b0d8161163b565b50565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60045481565b4173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610bad576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ba490611f71565b60405180910390fd5b6004544311610bf1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610be890612060565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610cc55750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663934e9a0382436040518363ffffffff1660e01b8152600401610c83929190612080565b602060405180830381865afa158015610ca0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc491906120e1565b5b61113c5760008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f8549af9436040518263ffffffff1660e01b8152600401610d259190611867565b602060405180830381865afa158015610d42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d669190611bbc565b90506000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060008154610dc79061210e565b9190508190559050600080610ddc8543610546565b915091506000610dec86866111c7565b9050818410158015610e22575060026003811115610e0d57610e0c611a33565b5b816003811115610e2057610e1f611a33565b5b105b15610f99576002600360008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600087815260200190815260200160002060006101000a81548160ff02191690836003811115610e9b57610e9a611a33565b5b02179055508573ffffffffffffffffffffffffffffffffffffffff167f8c2c2bfe532ccdb4523fa2392954fd58445929e7f260d786d0ab93cd981cde54600287604051610ee9929190612156565b60405180910390a260008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370f81f6c8760095443610f3c9190611d75565b6007546040518463ffffffff1660e01b8152600401610f5d93929190611f91565b600060405180830381600087803b158015610f7757600080fd5b505af1158015610f8b573d6000803e3d6000fd5b50505050505050505061113c565b828410158015610fcd575060016003811115610fb857610fb7611a33565b5b816003811115610fcb57610fca611a33565b5b105b15611136576001600360008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600087815260200190815260200160002060006101000a81548160ff0219169083600381111561104657611045611a33565b5b02179055508573ffffffffffffffffffffffffffffffffffffffff167f8c2c2bfe532ccdb4523fa2392954fd58445929e7f260d786d0ab93cd981cde54600187604051611094929190612156565b60405180910390a260008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370f81f6c876000806040518463ffffffff1660e01b81526004016110fa939291906121c4565b600060405180830381600087803b15801561111457600080fd5b505af1158015611128573d6000803e3d6000fd5b50505050505050505061113c565b50505050505b4360048190555050565b61114e6114eb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146111bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111b290611c6c565b60405180910390fd5b6111c48161167c565b50565b6000600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060009054906101000a900460ff16905092915050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080600554600654915091509091565b60075481565b6112786114eb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146112e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112dc90611c6c565b60405180910390fd5b6112ef82826116f6565b5050565b6000600160159054906101000a900460ff16159050808015611326575060018060149054906101000a900460ff1660ff16105b80611354575061133530611741565b158015611353575060018060149054906101000a900460ff1660ff16145b5b611393576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161138a9061226d565b60405180910390fd5b60018060146101000a81548160ff021916908360ff16021790555080156113cf5760018060156101000a81548160ff0219169083151502179055505b6113d88861167c565b6113e187611542565b6113eb85876116f6565b6113f48461163b565b6113fd83611764565b611406826115fa565b8015611460576000600160156101000a81548160ff0219169083151502179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498600160405161145791906122d5565b60405180910390a15b5050505050505050565b6114726114eb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146114df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114d690611c6c565b60405180910390fd5b6114e881611764565b50565b60006115197fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610360001b6117a5565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f31a33f126a5bae3c5bdf6cfc2cd6dcfffe2fe9634bdb09e21c44762993889e3b816040516115b29190611a18565b60405180910390a150565b60008383111580156115cf5750818411155b90509392505050565b60008183856115e79190611cbb565b6115f19190611d44565b90509392505050565b806009819055507f3092a623ebcf71b79f9f68801b081a4d0c839dfb4c0e6f9ff118f4fb870375dc816040516116309190611867565b60405180910390a150565b806007819055507f71491762d43dbadd94f85cf7a0322192a7c22f3ca4fb30de8895420607b56712816040516116719190611867565b60405180910390a150565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fef40dc07567635f84f5edbd2f8dbc16b40d9d282dd8e7e6f4ff58236b6836169816040516116eb9190611a18565b60405180910390a150565b81600681905550806005819055507f25a70459f14137ea646efb17b806c2e75632b931d69e642a8a809b6bfd7217a682826040516117359291906118ee565b60405180910390a15050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b806008819055507f42458d43c99c17f034dde22f3a1cf003e4bc27372c1ff14cb9e68a79a1b1e8ed8160405161179a9190611867565b60405180910390a150565b6000819050919050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006117ee826117c3565b9050919050565b6117fe816117e3565b811461180957600080fd5b50565b60008135905061181b816117f5565b92915050565b600060208284031215611837576118366117b9565b5b60006118458482850161180c565b91505092915050565b6000819050919050565b6118618161184e565b82525050565b600060208201905061187c6000830184611858565b92915050565b61188b8161184e565b811461189657600080fd5b50565b6000813590506118a881611882565b92915050565b600080604083850312156118c5576118c46117b9565b5b60006118d38582860161180c565b92505060206118e485828601611899565b9150509250929050565b60006040820190506119036000830185611858565b6119106020830184611858565b9392505050565b600080fd5b600080fd5b600080fd5b60008083601f84011261193c5761193b611917565b5b8235905067ffffffffffffffff8111156119595761195861191c565b5b60208301915083600182028301111561197557611974611921565b5b9250929050565b600080600060408486031215611995576119946117b9565b5b60006119a38682870161180c565b935050602084013567ffffffffffffffff8111156119c4576119c36117be565b5b6119d086828701611926565b92509250509250925092565b6000602082840312156119f2576119f16117b9565b5b6000611a0084828501611899565b91505092915050565b611a12816117e3565b82525050565b6000602082019050611a2d6000830184611a09565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110611a7357611a72611a33565b5b50565b6000819050611a8482611a62565b919050565b6000611a9482611a76565b9050919050565b611aa481611a89565b82525050565b6000602082019050611abf6000830184611a9b565b92915050565b60008060408385031215611adc57611adb6117b9565b5b6000611aea85828601611899565b9250506020611afb85828601611899565b9150509250929050565b600080600080600080600060e0888a031215611b2457611b236117b9565b5b6000611b328a828b0161180c565b9750506020611b438a828b0161180c565b9650506040611b548a828b01611899565b9550506060611b658a828b01611899565b9450506080611b768a828b01611899565b93505060a0611b878a828b01611899565b92505060c0611b988a828b01611899565b91505092959891949750929550565b600081519050611bb681611882565b92915050565b600060208284031215611bd257611bd16117b9565b5b6000611be084828501611ba7565b91505092915050565b600082825260208201905092915050565b7f48617350726f787941646d696e3a20756e617574686f72697a65642073656e6460008201527f6572000000000000000000000000000000000000000000000000000000000000602082015250565b6000611c56602283611be9565b9150611c6182611bfa565b604082019050919050565b60006020820190508181036000830152611c8581611c49565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000611cc68261184e565b9150611cd18361184e565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615611d0a57611d09611c8c565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000611d4f8261184e565b9150611d5a8361184e565b925082611d6a57611d69611d15565b5b828204905092915050565b6000611d808261184e565b9150611d8b8361184e565b9250828201905080821115611da357611da2611c8c565b5b92915050565b6000611db48261184e565b9150611dbf8361184e565b9250828203905081811115611dd757611dd6611c8c565b5b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b611e2b82611de2565b810181811067ffffffffffffffff82111715611e4a57611e49611df3565b5b80604052505050565b6000611e5d6117af565b9050611e698282611e22565b919050565b600060608284031215611e8457611e83611ddd565b5b611e8e6060611e53565b90506000611e9e84828501611ba7565b6000830152506020611eb284828501611ba7565b6020830152506040611ec684828501611ba7565b60408301525092915050565b600060608284031215611ee857611ee76117b9565b5b6000611ef684828501611e6e565b91505092915050565b7f536c617368496e64696361746f723a206d6574686f642063616c6c6572206d7560008201527f737420626520636f696e62617365000000000000000000000000000000000000602082015250565b6000611f5b602e83611be9565b9150611f6682611eff565b604082019050919050565b60006020820190508181036000830152611f8a81611f4e565b9050919050565b6000606082019050611fa66000830186611a09565b611fb36020830185611858565b611fc06040830184611858565b949350505050565b7f536c617368496e64696361746f723a2063616e6e6f7420736c6173682061207660008201527f616c696461746f72207477696365206f7220736c617368206d6f72652074686160208201527f6e206f6e652076616c696461746f7220696e206f6e6520626c6f636b00000000604082015250565b600061204a605c83611be9565b915061205582611fc8565b606082019050919050565b600060208201905081810360008301526120798161203d565b9050919050565b60006040820190506120956000830185611a09565b6120a26020830184611858565b9392505050565b60008115159050919050565b6120be816120a9565b81146120c957600080fd5b50565b6000815190506120db816120b5565b92915050565b6000602082840312156120f7576120f66117b9565b5b6000612105848285016120cc565b91505092915050565b60006121198261184e565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361214b5761214a611c8c565b5b600182019050919050565b600060408201905061216b6000830185611a9b565b6121786020830184611858565b9392505050565b6000819050919050565b6000819050919050565b60006121ae6121a96121a48461217f565b612189565b61184e565b9050919050565b6121be81612193565b82525050565b60006060820190506121d96000830186611a09565b6121e660208301856121b5565b6121f360408301846121b5565b949350505050565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b6000612257602e83611be9565b9150612262826121fb565b604082019050919050565b600060208201905081810360008301526122868161224a565b9050919050565b6000819050919050565b600060ff82169050919050565b60006122bf6122ba6122b58461228d565b612189565b612297565b9050919050565b6122cf816122a4565b82525050565b60006020820190506122ea60008301846122c6565b9291505056fea2646970667358221220596bf6931e5e1ac6d2a596b7742c7865bf6a8c1a711329b22248ebcace8f47d064736f6c63430008100033", } // SlashIndicatorABI is the input ABI used to generate the binding from. @@ -43,7 +43,7 @@ var SlashIndicatorABI = SlashIndicatorMetaData.ABI var SlashIndicatorBin = SlashIndicatorMetaData.Bin // DeploySlashIndicator deploys a new Ethereum contract, binding an instance of SlashIndicator to it. -func DeploySlashIndicator(auth *bind.TransactOpts, backend bind.ContractBackend, _validatorSetContract common.Address) (common.Address, *types.Transaction, *SlashIndicator, error) { +func DeploySlashIndicator(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *SlashIndicator, error) { parsed, err := SlashIndicatorMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -52,7 +52,7 @@ func DeploySlashIndicator(auth *bind.TransactOpts, backend bind.ContractBackend, return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(SlashIndicatorBin), backend, _validatorSetContract) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(SlashIndicatorBin), backend) if err != nil { return common.Address{}, nil, nil, err } @@ -201,6 +201,68 @@ func (_SlashIndicator *SlashIndicatorTransactorRaw) Transact(opts *bind.Transact return _SlashIndicator.Contract.contract.Transact(opts, method, params...) } +// CurrentUnavailabilityIndicator is a free data retrieval call binding the contract method 0x082e7420. +// +// Solidity: function currentUnavailabilityIndicator(address _validator) view returns(uint256) +func (_SlashIndicator *SlashIndicatorCaller) CurrentUnavailabilityIndicator(opts *bind.CallOpts, _validator common.Address) (*big.Int, error) { + var out []interface{} + err := _SlashIndicator.contract.Call(opts, &out, "currentUnavailabilityIndicator", _validator) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// CurrentUnavailabilityIndicator is a free data retrieval call binding the contract method 0x082e7420. +// +// Solidity: function currentUnavailabilityIndicator(address _validator) view returns(uint256) +func (_SlashIndicator *SlashIndicatorSession) CurrentUnavailabilityIndicator(_validator common.Address) (*big.Int, error) { + return _SlashIndicator.Contract.CurrentUnavailabilityIndicator(&_SlashIndicator.CallOpts, _validator) +} + +// CurrentUnavailabilityIndicator is a free data retrieval call binding the contract method 0x082e7420. +// +// Solidity: function currentUnavailabilityIndicator(address _validator) view returns(uint256) +func (_SlashIndicator *SlashIndicatorCallerSession) CurrentUnavailabilityIndicator(_validator common.Address) (*big.Int, error) { + return _SlashIndicator.Contract.CurrentUnavailabilityIndicator(&_SlashIndicator.CallOpts, _validator) +} + +// FelonyJailDuration is a free data retrieval call binding the contract method 0x6b79f95f. +// +// Solidity: function felonyJailDuration() view returns(uint256) +func (_SlashIndicator *SlashIndicatorCaller) FelonyJailDuration(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _SlashIndicator.contract.Call(opts, &out, "felonyJailDuration") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// FelonyJailDuration is a free data retrieval call binding the contract method 0x6b79f95f. +// +// Solidity: function felonyJailDuration() view returns(uint256) +func (_SlashIndicator *SlashIndicatorSession) FelonyJailDuration() (*big.Int, error) { + return _SlashIndicator.Contract.FelonyJailDuration(&_SlashIndicator.CallOpts) +} + +// FelonyJailDuration is a free data retrieval call binding the contract method 0x6b79f95f. +// +// Solidity: function felonyJailDuration() view returns(uint256) +func (_SlashIndicator *SlashIndicatorCallerSession) FelonyJailDuration() (*big.Int, error) { + return _SlashIndicator.Contract.FelonyJailDuration(&_SlashIndicator.CallOpts) +} + // FelonyThreshold is a free data retrieval call binding the contract method 0x389f4f71. // // Solidity: function felonyThreshold() view returns(uint256) @@ -232,12 +294,12 @@ func (_SlashIndicator *SlashIndicatorCallerSession) FelonyThreshold() (*big.Int, return _SlashIndicator.Contract.FelonyThreshold(&_SlashIndicator.CallOpts) } -// GetSlashIndicator is a free data retrieval call binding the contract method 0x37c8dab9. +// GetUnavailabilityIndicator is a free data retrieval call binding the contract method 0x62ffe6cb. // -// Solidity: function getSlashIndicator(address validator) view returns(uint256) -func (_SlashIndicator *SlashIndicatorCaller) GetSlashIndicator(opts *bind.CallOpts, validator common.Address) (*big.Int, error) { +// Solidity: function getUnavailabilityIndicator(address _validator, uint256 _period) view returns(uint256) +func (_SlashIndicator *SlashIndicatorCaller) GetUnavailabilityIndicator(opts *bind.CallOpts, _validator common.Address, _period *big.Int) (*big.Int, error) { var out []interface{} - err := _SlashIndicator.contract.Call(opts, &out, "getSlashIndicator", validator) + err := _SlashIndicator.contract.Call(opts, &out, "getUnavailabilityIndicator", _validator, _period) if err != nil { return *new(*big.Int), err @@ -249,26 +311,57 @@ func (_SlashIndicator *SlashIndicatorCaller) GetSlashIndicator(opts *bind.CallOp } -// GetSlashIndicator is a free data retrieval call binding the contract method 0x37c8dab9. +// GetUnavailabilityIndicator is a free data retrieval call binding the contract method 0x62ffe6cb. +// +// Solidity: function getUnavailabilityIndicator(address _validator, uint256 _period) view returns(uint256) +func (_SlashIndicator *SlashIndicatorSession) GetUnavailabilityIndicator(_validator common.Address, _period *big.Int) (*big.Int, error) { + return _SlashIndicator.Contract.GetUnavailabilityIndicator(&_SlashIndicator.CallOpts, _validator, _period) +} + +// GetUnavailabilityIndicator is a free data retrieval call binding the contract method 0x62ffe6cb. +// +// Solidity: function getUnavailabilityIndicator(address _validator, uint256 _period) view returns(uint256) +func (_SlashIndicator *SlashIndicatorCallerSession) GetUnavailabilityIndicator(_validator common.Address, _period *big.Int) (*big.Int, error) { + return _SlashIndicator.Contract.GetUnavailabilityIndicator(&_SlashIndicator.CallOpts, _validator, _period) +} + +// GetUnavailabilitySlashType is a free data retrieval call binding the contract method 0xd180ecb0. +// +// Solidity: function getUnavailabilitySlashType(address _validatorAddr, uint256 _period) view returns(uint8) +func (_SlashIndicator *SlashIndicatorCaller) GetUnavailabilitySlashType(opts *bind.CallOpts, _validatorAddr common.Address, _period *big.Int) (uint8, error) { + var out []interface{} + err := _SlashIndicator.contract.Call(opts, &out, "getUnavailabilitySlashType", _validatorAddr, _period) + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// GetUnavailabilitySlashType is a free data retrieval call binding the contract method 0xd180ecb0. // -// Solidity: function getSlashIndicator(address validator) view returns(uint256) -func (_SlashIndicator *SlashIndicatorSession) GetSlashIndicator(validator common.Address) (*big.Int, error) { - return _SlashIndicator.Contract.GetSlashIndicator(&_SlashIndicator.CallOpts, validator) +// Solidity: function getUnavailabilitySlashType(address _validatorAddr, uint256 _period) view returns(uint8) +func (_SlashIndicator *SlashIndicatorSession) GetUnavailabilitySlashType(_validatorAddr common.Address, _period *big.Int) (uint8, error) { + return _SlashIndicator.Contract.GetUnavailabilitySlashType(&_SlashIndicator.CallOpts, _validatorAddr, _period) } -// GetSlashIndicator is a free data retrieval call binding the contract method 0x37c8dab9. +// GetUnavailabilitySlashType is a free data retrieval call binding the contract method 0xd180ecb0. // -// Solidity: function getSlashIndicator(address validator) view returns(uint256) -func (_SlashIndicator *SlashIndicatorCallerSession) GetSlashIndicator(validator common.Address) (*big.Int, error) { - return _SlashIndicator.Contract.GetSlashIndicator(&_SlashIndicator.CallOpts, validator) +// Solidity: function getUnavailabilitySlashType(address _validatorAddr, uint256 _period) view returns(uint8) +func (_SlashIndicator *SlashIndicatorCallerSession) GetUnavailabilitySlashType(_validatorAddr common.Address, _period *big.Int) (uint8, error) { + return _SlashIndicator.Contract.GetUnavailabilitySlashType(&_SlashIndicator.CallOpts, _validatorAddr, _period) } -// GetSlashThresholds is a free data retrieval call binding the contract method 0x8256ace6. +// GetUnavailabilityThresholds is a free data retrieval call binding the contract method 0xd9193587. // -// Solidity: function getSlashThresholds() view returns(uint256, uint256) -func (_SlashIndicator *SlashIndicatorCaller) GetSlashThresholds(opts *bind.CallOpts) (*big.Int, *big.Int, error) { +// Solidity: function getUnavailabilityThresholds() view returns(uint256, uint256) +func (_SlashIndicator *SlashIndicatorCaller) GetUnavailabilityThresholds(opts *bind.CallOpts) (*big.Int, *big.Int, error) { var out []interface{} - err := _SlashIndicator.contract.Call(opts, &out, "getSlashThresholds") + err := _SlashIndicator.contract.Call(opts, &out, "getUnavailabilityThresholds") if err != nil { return *new(*big.Int), *new(*big.Int), err @@ -281,18 +374,18 @@ func (_SlashIndicator *SlashIndicatorCaller) GetSlashThresholds(opts *bind.CallO } -// GetSlashThresholds is a free data retrieval call binding the contract method 0x8256ace6. +// GetUnavailabilityThresholds is a free data retrieval call binding the contract method 0xd9193587. // -// Solidity: function getSlashThresholds() view returns(uint256, uint256) -func (_SlashIndicator *SlashIndicatorSession) GetSlashThresholds() (*big.Int, *big.Int, error) { - return _SlashIndicator.Contract.GetSlashThresholds(&_SlashIndicator.CallOpts) +// Solidity: function getUnavailabilityThresholds() view returns(uint256, uint256) +func (_SlashIndicator *SlashIndicatorSession) GetUnavailabilityThresholds() (*big.Int, *big.Int, error) { + return _SlashIndicator.Contract.GetUnavailabilityThresholds(&_SlashIndicator.CallOpts) } -// GetSlashThresholds is a free data retrieval call binding the contract method 0x8256ace6. +// GetUnavailabilityThresholds is a free data retrieval call binding the contract method 0xd9193587. // -// Solidity: function getSlashThresholds() view returns(uint256, uint256) -func (_SlashIndicator *SlashIndicatorCallerSession) GetSlashThresholds() (*big.Int, *big.Int, error) { - return _SlashIndicator.Contract.GetSlashThresholds(&_SlashIndicator.CallOpts) +// Solidity: function getUnavailabilityThresholds() view returns(uint256, uint256) +func (_SlashIndicator *SlashIndicatorCallerSession) GetUnavailabilityThresholds() (*big.Int, *big.Int, error) { + return _SlashIndicator.Contract.GetUnavailabilityThresholds(&_SlashIndicator.CallOpts) } // LastSlashedBlock is a free data retrieval call binding the contract method 0xaef250be. @@ -326,6 +419,37 @@ func (_SlashIndicator *SlashIndicatorCallerSession) LastSlashedBlock() (*big.Int return _SlashIndicator.Contract.LastSlashedBlock(&_SlashIndicator.CallOpts) } +// MaintenanceContract is a free data retrieval call binding the contract method 0xd2cb215e. +// +// Solidity: function maintenanceContract() view returns(address) +func (_SlashIndicator *SlashIndicatorCaller) MaintenanceContract(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _SlashIndicator.contract.Call(opts, &out, "maintenanceContract") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// MaintenanceContract is a free data retrieval call binding the contract method 0xd2cb215e. +// +// Solidity: function maintenanceContract() view returns(address) +func (_SlashIndicator *SlashIndicatorSession) MaintenanceContract() (common.Address, error) { + return _SlashIndicator.Contract.MaintenanceContract(&_SlashIndicator.CallOpts) +} + +// MaintenanceContract is a free data retrieval call binding the contract method 0xd2cb215e. +// +// Solidity: function maintenanceContract() view returns(address) +func (_SlashIndicator *SlashIndicatorCallerSession) MaintenanceContract() (common.Address, error) { + return _SlashIndicator.Contract.MaintenanceContract(&_SlashIndicator.CallOpts) +} + // MisdemeanorThreshold is a free data retrieval call binding the contract method 0x567a372d. // // Solidity: function misdemeanorThreshold() view returns(uint256) @@ -357,6 +481,113 @@ func (_SlashIndicator *SlashIndicatorCallerSession) MisdemeanorThreshold() (*big return _SlashIndicator.Contract.MisdemeanorThreshold(&_SlashIndicator.CallOpts) } +// SlashDoubleSignAmount is a free data retrieval call binding the contract method 0x6d14c4e5. +// +// Solidity: function slashDoubleSignAmount() view returns(uint256) +func (_SlashIndicator *SlashIndicatorCaller) SlashDoubleSignAmount(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _SlashIndicator.contract.Call(opts, &out, "slashDoubleSignAmount") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// SlashDoubleSignAmount is a free data retrieval call binding the contract method 0x6d14c4e5. +// +// Solidity: function slashDoubleSignAmount() view returns(uint256) +func (_SlashIndicator *SlashIndicatorSession) SlashDoubleSignAmount() (*big.Int, error) { + return _SlashIndicator.Contract.SlashDoubleSignAmount(&_SlashIndicator.CallOpts) +} + +// SlashDoubleSignAmount is a free data retrieval call binding the contract method 0x6d14c4e5. +// +// Solidity: function slashDoubleSignAmount() view returns(uint256) +func (_SlashIndicator *SlashIndicatorCallerSession) SlashDoubleSignAmount() (*big.Int, error) { + return _SlashIndicator.Contract.SlashDoubleSignAmount(&_SlashIndicator.CallOpts) +} + +// SlashFelonyAmount is a free data retrieval call binding the contract method 0xdfe484cb. +// +// Solidity: function slashFelonyAmount() view returns(uint256) +func (_SlashIndicator *SlashIndicatorCaller) SlashFelonyAmount(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _SlashIndicator.contract.Call(opts, &out, "slashFelonyAmount") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// SlashFelonyAmount is a free data retrieval call binding the contract method 0xdfe484cb. +// +// Solidity: function slashFelonyAmount() view returns(uint256) +func (_SlashIndicator *SlashIndicatorSession) SlashFelonyAmount() (*big.Int, error) { + return _SlashIndicator.Contract.SlashFelonyAmount(&_SlashIndicator.CallOpts) +} + +// SlashFelonyAmount is a free data retrieval call binding the contract method 0xdfe484cb. +// +// Solidity: function slashFelonyAmount() view returns(uint256) +func (_SlashIndicator *SlashIndicatorCallerSession) SlashFelonyAmount() (*big.Int, error) { + return _SlashIndicator.Contract.SlashFelonyAmount(&_SlashIndicator.CallOpts) +} + +// UnavailabilityThresholdsOf is a free data retrieval call binding the contract method 0x4d961e18. +// +// Solidity: function unavailabilityThresholdsOf(address _addr, uint256 _block) view returns(uint256 _misdemeanorThreshold, uint256 _felonyThreshold) +func (_SlashIndicator *SlashIndicatorCaller) UnavailabilityThresholdsOf(opts *bind.CallOpts, _addr common.Address, _block *big.Int) (struct { + MisdemeanorThreshold *big.Int + FelonyThreshold *big.Int +}, error) { + var out []interface{} + err := _SlashIndicator.contract.Call(opts, &out, "unavailabilityThresholdsOf", _addr, _block) + + outstruct := new(struct { + MisdemeanorThreshold *big.Int + FelonyThreshold *big.Int + }) + if err != nil { + return *outstruct, err + } + + outstruct.MisdemeanorThreshold = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + outstruct.FelonyThreshold = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +// UnavailabilityThresholdsOf is a free data retrieval call binding the contract method 0x4d961e18. +// +// Solidity: function unavailabilityThresholdsOf(address _addr, uint256 _block) view returns(uint256 _misdemeanorThreshold, uint256 _felonyThreshold) +func (_SlashIndicator *SlashIndicatorSession) UnavailabilityThresholdsOf(_addr common.Address, _block *big.Int) (struct { + MisdemeanorThreshold *big.Int + FelonyThreshold *big.Int +}, error) { + return _SlashIndicator.Contract.UnavailabilityThresholdsOf(&_SlashIndicator.CallOpts, _addr, _block) +} + +// UnavailabilityThresholdsOf is a free data retrieval call binding the contract method 0x4d961e18. +// +// Solidity: function unavailabilityThresholdsOf(address _addr, uint256 _block) view returns(uint256 _misdemeanorThreshold, uint256 _felonyThreshold) +func (_SlashIndicator *SlashIndicatorCallerSession) UnavailabilityThresholdsOf(_addr common.Address, _block *big.Int) (struct { + MisdemeanorThreshold *big.Int + FelonyThreshold *big.Int +}, error) { + return _SlashIndicator.Contract.UnavailabilityThresholdsOf(&_SlashIndicator.CallOpts, _addr, _block) +} + // ValidatorContract is a free data retrieval call binding the contract method 0x99439089. // // Solidity: function validatorContract() view returns(address) @@ -388,25 +619,151 @@ func (_SlashIndicator *SlashIndicatorCallerSession) ValidatorContract() (common. return _SlashIndicator.Contract.ValidatorContract(&_SlashIndicator.CallOpts) } -// ResetCounters is a paid mutator transaction binding the contract method 0xec35fe72. +// Initialize is a paid mutator transaction binding the contract method 0xedbf4ac2. // -// Solidity: function resetCounters(address[] _validatorAddrs) returns() -func (_SlashIndicator *SlashIndicatorTransactor) ResetCounters(opts *bind.TransactOpts, _validatorAddrs []common.Address) (*types.Transaction, error) { - return _SlashIndicator.contract.Transact(opts, "resetCounters", _validatorAddrs) +// Solidity: function initialize(address __validatorContract, address __maintenanceContract, uint256 _misdemeanorThreshold, uint256 _felonyThreshold, uint256 _slashFelonyAmount, uint256 _slashDoubleSignAmount, uint256 _felonyJailBlocks) returns() +func (_SlashIndicator *SlashIndicatorTransactor) Initialize(opts *bind.TransactOpts, __validatorContract common.Address, __maintenanceContract common.Address, _misdemeanorThreshold *big.Int, _felonyThreshold *big.Int, _slashFelonyAmount *big.Int, _slashDoubleSignAmount *big.Int, _felonyJailBlocks *big.Int) (*types.Transaction, error) { + return _SlashIndicator.contract.Transact(opts, "initialize", __validatorContract, __maintenanceContract, _misdemeanorThreshold, _felonyThreshold, _slashFelonyAmount, _slashDoubleSignAmount, _felonyJailBlocks) } -// ResetCounters is a paid mutator transaction binding the contract method 0xec35fe72. +// Initialize is a paid mutator transaction binding the contract method 0xedbf4ac2. // -// Solidity: function resetCounters(address[] _validatorAddrs) returns() -func (_SlashIndicator *SlashIndicatorSession) ResetCounters(_validatorAddrs []common.Address) (*types.Transaction, error) { - return _SlashIndicator.Contract.ResetCounters(&_SlashIndicator.TransactOpts, _validatorAddrs) +// Solidity: function initialize(address __validatorContract, address __maintenanceContract, uint256 _misdemeanorThreshold, uint256 _felonyThreshold, uint256 _slashFelonyAmount, uint256 _slashDoubleSignAmount, uint256 _felonyJailBlocks) returns() +func (_SlashIndicator *SlashIndicatorSession) Initialize(__validatorContract common.Address, __maintenanceContract common.Address, _misdemeanorThreshold *big.Int, _felonyThreshold *big.Int, _slashFelonyAmount *big.Int, _slashDoubleSignAmount *big.Int, _felonyJailBlocks *big.Int) (*types.Transaction, error) { + return _SlashIndicator.Contract.Initialize(&_SlashIndicator.TransactOpts, __validatorContract, __maintenanceContract, _misdemeanorThreshold, _felonyThreshold, _slashFelonyAmount, _slashDoubleSignAmount, _felonyJailBlocks) } -// ResetCounters is a paid mutator transaction binding the contract method 0xec35fe72. +// Initialize is a paid mutator transaction binding the contract method 0xedbf4ac2. // -// Solidity: function resetCounters(address[] _validatorAddrs) returns() -func (_SlashIndicator *SlashIndicatorTransactorSession) ResetCounters(_validatorAddrs []common.Address) (*types.Transaction, error) { - return _SlashIndicator.Contract.ResetCounters(&_SlashIndicator.TransactOpts, _validatorAddrs) +// Solidity: function initialize(address __validatorContract, address __maintenanceContract, uint256 _misdemeanorThreshold, uint256 _felonyThreshold, uint256 _slashFelonyAmount, uint256 _slashDoubleSignAmount, uint256 _felonyJailBlocks) returns() +func (_SlashIndicator *SlashIndicatorTransactorSession) Initialize(__validatorContract common.Address, __maintenanceContract common.Address, _misdemeanorThreshold *big.Int, _felonyThreshold *big.Int, _slashFelonyAmount *big.Int, _slashDoubleSignAmount *big.Int, _felonyJailBlocks *big.Int) (*types.Transaction, error) { + return _SlashIndicator.Contract.Initialize(&_SlashIndicator.TransactOpts, __validatorContract, __maintenanceContract, _misdemeanorThreshold, _felonyThreshold, _slashFelonyAmount, _slashDoubleSignAmount, _felonyJailBlocks) +} + +// SetFelonyJailDuration is a paid mutator transaction binding the contract method 0x5786e9ee. +// +// Solidity: function setFelonyJailDuration(uint256 _felonyJailDuration) returns() +func (_SlashIndicator *SlashIndicatorTransactor) SetFelonyJailDuration(opts *bind.TransactOpts, _felonyJailDuration *big.Int) (*types.Transaction, error) { + return _SlashIndicator.contract.Transact(opts, "setFelonyJailDuration", _felonyJailDuration) +} + +// SetFelonyJailDuration is a paid mutator transaction binding the contract method 0x5786e9ee. +// +// Solidity: function setFelonyJailDuration(uint256 _felonyJailDuration) returns() +func (_SlashIndicator *SlashIndicatorSession) SetFelonyJailDuration(_felonyJailDuration *big.Int) (*types.Transaction, error) { + return _SlashIndicator.Contract.SetFelonyJailDuration(&_SlashIndicator.TransactOpts, _felonyJailDuration) +} + +// SetFelonyJailDuration is a paid mutator transaction binding the contract method 0x5786e9ee. +// +// Solidity: function setFelonyJailDuration(uint256 _felonyJailDuration) returns() +func (_SlashIndicator *SlashIndicatorTransactorSession) SetFelonyJailDuration(_felonyJailDuration *big.Int) (*types.Transaction, error) { + return _SlashIndicator.Contract.SetFelonyJailDuration(&_SlashIndicator.TransactOpts, _felonyJailDuration) +} + +// SetMaintenanceContract is a paid mutator transaction binding the contract method 0x46fe9311. +// +// Solidity: function setMaintenanceContract(address _addr) returns() +func (_SlashIndicator *SlashIndicatorTransactor) SetMaintenanceContract(opts *bind.TransactOpts, _addr common.Address) (*types.Transaction, error) { + return _SlashIndicator.contract.Transact(opts, "setMaintenanceContract", _addr) +} + +// SetMaintenanceContract is a paid mutator transaction binding the contract method 0x46fe9311. +// +// Solidity: function setMaintenanceContract(address _addr) returns() +func (_SlashIndicator *SlashIndicatorSession) SetMaintenanceContract(_addr common.Address) (*types.Transaction, error) { + return _SlashIndicator.Contract.SetMaintenanceContract(&_SlashIndicator.TransactOpts, _addr) +} + +// SetMaintenanceContract is a paid mutator transaction binding the contract method 0x46fe9311. +// +// Solidity: function setMaintenanceContract(address _addr) returns() +func (_SlashIndicator *SlashIndicatorTransactorSession) SetMaintenanceContract(_addr common.Address) (*types.Transaction, error) { + return _SlashIndicator.Contract.SetMaintenanceContract(&_SlashIndicator.TransactOpts, _addr) +} + +// SetSlashDoubleSignAmount is a paid mutator transaction binding the contract method 0xf82bdd01. +// +// Solidity: function setSlashDoubleSignAmount(uint256 _slashDoubleSignAmount) returns() +func (_SlashIndicator *SlashIndicatorTransactor) SetSlashDoubleSignAmount(opts *bind.TransactOpts, _slashDoubleSignAmount *big.Int) (*types.Transaction, error) { + return _SlashIndicator.contract.Transact(opts, "setSlashDoubleSignAmount", _slashDoubleSignAmount) +} + +// SetSlashDoubleSignAmount is a paid mutator transaction binding the contract method 0xf82bdd01. +// +// Solidity: function setSlashDoubleSignAmount(uint256 _slashDoubleSignAmount) returns() +func (_SlashIndicator *SlashIndicatorSession) SetSlashDoubleSignAmount(_slashDoubleSignAmount *big.Int) (*types.Transaction, error) { + return _SlashIndicator.Contract.SetSlashDoubleSignAmount(&_SlashIndicator.TransactOpts, _slashDoubleSignAmount) +} + +// SetSlashDoubleSignAmount is a paid mutator transaction binding the contract method 0xf82bdd01. +// +// Solidity: function setSlashDoubleSignAmount(uint256 _slashDoubleSignAmount) returns() +func (_SlashIndicator *SlashIndicatorTransactorSession) SetSlashDoubleSignAmount(_slashDoubleSignAmount *big.Int) (*types.Transaction, error) { + return _SlashIndicator.Contract.SetSlashDoubleSignAmount(&_SlashIndicator.TransactOpts, _slashDoubleSignAmount) +} + +// SetSlashFelonyAmount is a paid mutator transaction binding the contract method 0x6e91bec5. +// +// Solidity: function setSlashFelonyAmount(uint256 _slashFelonyAmount) returns() +func (_SlashIndicator *SlashIndicatorTransactor) SetSlashFelonyAmount(opts *bind.TransactOpts, _slashFelonyAmount *big.Int) (*types.Transaction, error) { + return _SlashIndicator.contract.Transact(opts, "setSlashFelonyAmount", _slashFelonyAmount) +} + +// SetSlashFelonyAmount is a paid mutator transaction binding the contract method 0x6e91bec5. +// +// Solidity: function setSlashFelonyAmount(uint256 _slashFelonyAmount) returns() +func (_SlashIndicator *SlashIndicatorSession) SetSlashFelonyAmount(_slashFelonyAmount *big.Int) (*types.Transaction, error) { + return _SlashIndicator.Contract.SetSlashFelonyAmount(&_SlashIndicator.TransactOpts, _slashFelonyAmount) +} + +// SetSlashFelonyAmount is a paid mutator transaction binding the contract method 0x6e91bec5. +// +// Solidity: function setSlashFelonyAmount(uint256 _slashFelonyAmount) returns() +func (_SlashIndicator *SlashIndicatorTransactorSession) SetSlashFelonyAmount(_slashFelonyAmount *big.Int) (*types.Transaction, error) { + return _SlashIndicator.Contract.SetSlashFelonyAmount(&_SlashIndicator.TransactOpts, _slashFelonyAmount) +} + +// SetSlashThresholds is a paid mutator transaction binding the contract method 0xe4f9c4be. +// +// Solidity: function setSlashThresholds(uint256 _felonyThreshold, uint256 _misdemeanorThreshold) returns() +func (_SlashIndicator *SlashIndicatorTransactor) SetSlashThresholds(opts *bind.TransactOpts, _felonyThreshold *big.Int, _misdemeanorThreshold *big.Int) (*types.Transaction, error) { + return _SlashIndicator.contract.Transact(opts, "setSlashThresholds", _felonyThreshold, _misdemeanorThreshold) +} + +// SetSlashThresholds is a paid mutator transaction binding the contract method 0xe4f9c4be. +// +// Solidity: function setSlashThresholds(uint256 _felonyThreshold, uint256 _misdemeanorThreshold) returns() +func (_SlashIndicator *SlashIndicatorSession) SetSlashThresholds(_felonyThreshold *big.Int, _misdemeanorThreshold *big.Int) (*types.Transaction, error) { + return _SlashIndicator.Contract.SetSlashThresholds(&_SlashIndicator.TransactOpts, _felonyThreshold, _misdemeanorThreshold) +} + +// SetSlashThresholds is a paid mutator transaction binding the contract method 0xe4f9c4be. +// +// Solidity: function setSlashThresholds(uint256 _felonyThreshold, uint256 _misdemeanorThreshold) returns() +func (_SlashIndicator *SlashIndicatorTransactorSession) SetSlashThresholds(_felonyThreshold *big.Int, _misdemeanorThreshold *big.Int) (*types.Transaction, error) { + return _SlashIndicator.Contract.SetSlashThresholds(&_SlashIndicator.TransactOpts, _felonyThreshold, _misdemeanorThreshold) +} + +// SetValidatorContract is a paid mutator transaction binding the contract method 0xcdf64a76. +// +// Solidity: function setValidatorContract(address _addr) returns() +func (_SlashIndicator *SlashIndicatorTransactor) SetValidatorContract(opts *bind.TransactOpts, _addr common.Address) (*types.Transaction, error) { + return _SlashIndicator.contract.Transact(opts, "setValidatorContract", _addr) +} + +// SetValidatorContract is a paid mutator transaction binding the contract method 0xcdf64a76. +// +// Solidity: function setValidatorContract(address _addr) returns() +func (_SlashIndicator *SlashIndicatorSession) SetValidatorContract(_addr common.Address) (*types.Transaction, error) { + return _SlashIndicator.Contract.SetValidatorContract(&_SlashIndicator.TransactOpts, _addr) +} + +// SetValidatorContract is a paid mutator transaction binding the contract method 0xcdf64a76. +// +// Solidity: function setValidatorContract(address _addr) returns() +func (_SlashIndicator *SlashIndicatorTransactorSession) SetValidatorContract(_addr common.Address) (*types.Transaction, error) { + return _SlashIndicator.Contract.SetValidatorContract(&_SlashIndicator.TransactOpts, _addr) } // Slash is a paid mutator transaction binding the contract method 0xc96be4cb. @@ -432,28 +789,28 @@ func (_SlashIndicator *SlashIndicatorTransactorSession) Slash(_validatorAddr com // SlashDoubleSign is a paid mutator transaction binding the contract method 0x518e463a. // -// Solidity: function slashDoubleSign(address _valAddr, bytes _evidence) returns() -func (_SlashIndicator *SlashIndicatorTransactor) SlashDoubleSign(opts *bind.TransactOpts, _valAddr common.Address, _evidence []byte) (*types.Transaction, error) { - return _SlashIndicator.contract.Transact(opts, "slashDoubleSign", _valAddr, _evidence) +// Solidity: function slashDoubleSign(address _validatorAddr, bytes ) returns() +func (_SlashIndicator *SlashIndicatorTransactor) SlashDoubleSign(opts *bind.TransactOpts, _validatorAddr common.Address, arg1 []byte) (*types.Transaction, error) { + return _SlashIndicator.contract.Transact(opts, "slashDoubleSign", _validatorAddr, arg1) } // SlashDoubleSign is a paid mutator transaction binding the contract method 0x518e463a. // -// Solidity: function slashDoubleSign(address _valAddr, bytes _evidence) returns() -func (_SlashIndicator *SlashIndicatorSession) SlashDoubleSign(_valAddr common.Address, _evidence []byte) (*types.Transaction, error) { - return _SlashIndicator.Contract.SlashDoubleSign(&_SlashIndicator.TransactOpts, _valAddr, _evidence) +// Solidity: function slashDoubleSign(address _validatorAddr, bytes ) returns() +func (_SlashIndicator *SlashIndicatorSession) SlashDoubleSign(_validatorAddr common.Address, arg1 []byte) (*types.Transaction, error) { + return _SlashIndicator.Contract.SlashDoubleSign(&_SlashIndicator.TransactOpts, _validatorAddr, arg1) } // SlashDoubleSign is a paid mutator transaction binding the contract method 0x518e463a. // -// Solidity: function slashDoubleSign(address _valAddr, bytes _evidence) returns() -func (_SlashIndicator *SlashIndicatorTransactorSession) SlashDoubleSign(_valAddr common.Address, _evidence []byte) (*types.Transaction, error) { - return _SlashIndicator.Contract.SlashDoubleSign(&_SlashIndicator.TransactOpts, _valAddr, _evidence) +// Solidity: function slashDoubleSign(address _validatorAddr, bytes ) returns() +func (_SlashIndicator *SlashIndicatorTransactorSession) SlashDoubleSign(_validatorAddr common.Address, arg1 []byte) (*types.Transaction, error) { + return _SlashIndicator.Contract.SlashDoubleSign(&_SlashIndicator.TransactOpts, _validatorAddr, arg1) } -// SlashIndicatorUnavailabilityIndicatorsResetIterator is returned from FilterUnavailabilityIndicatorsReset and is used to iterate over the raw logs and unpacked data for UnavailabilityIndicatorsReset events raised by the SlashIndicator contract. -type SlashIndicatorUnavailabilityIndicatorsResetIterator struct { - Event *SlashIndicatorUnavailabilityIndicatorsReset // Event containing the contract specifics and raw log +// SlashIndicatorFelonyJailDurationUpdatedIterator is returned from FilterFelonyJailDurationUpdated and is used to iterate over the raw logs and unpacked data for FelonyJailDurationUpdated events raised by the SlashIndicator contract. +type SlashIndicatorFelonyJailDurationUpdatedIterator struct { + Event *SlashIndicatorFelonyJailDurationUpdated // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -467,7 +824,7 @@ type SlashIndicatorUnavailabilityIndicatorsResetIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *SlashIndicatorUnavailabilityIndicatorsResetIterator) Next() bool { +func (it *SlashIndicatorFelonyJailDurationUpdatedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -476,7 +833,7 @@ func (it *SlashIndicatorUnavailabilityIndicatorsResetIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(SlashIndicatorUnavailabilityIndicatorsReset) + it.Event = new(SlashIndicatorFelonyJailDurationUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -491,7 +848,7 @@ func (it *SlashIndicatorUnavailabilityIndicatorsResetIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(SlashIndicatorUnavailabilityIndicatorsReset) + it.Event = new(SlashIndicatorFelonyJailDurationUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -507,41 +864,41 @@ func (it *SlashIndicatorUnavailabilityIndicatorsResetIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *SlashIndicatorUnavailabilityIndicatorsResetIterator) Error() error { +func (it *SlashIndicatorFelonyJailDurationUpdatedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *SlashIndicatorUnavailabilityIndicatorsResetIterator) Close() error { +func (it *SlashIndicatorFelonyJailDurationUpdatedIterator) Close() error { it.sub.Unsubscribe() return nil } -// SlashIndicatorUnavailabilityIndicatorsReset represents a UnavailabilityIndicatorsReset event raised by the SlashIndicator contract. -type SlashIndicatorUnavailabilityIndicatorsReset struct { - Validators []common.Address - Raw types.Log // Blockchain specific contextual infos +// SlashIndicatorFelonyJailDurationUpdated represents a FelonyJailDurationUpdated event raised by the SlashIndicator contract. +type SlashIndicatorFelonyJailDurationUpdated struct { + FelonyJailDuration *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterUnavailabilityIndicatorsReset is a free log retrieval operation binding the contract event 0x9ae71e4f83d6019cd988ca4c38a696d015d5f6e41f3fd708fb746d2b672b4996. +// FilterFelonyJailDurationUpdated is a free log retrieval operation binding the contract event 0x3092a623ebcf71b79f9f68801b081a4d0c839dfb4c0e6f9ff118f4fb870375dc. // -// Solidity: event UnavailabilityIndicatorsReset(address[] validators) -func (_SlashIndicator *SlashIndicatorFilterer) FilterUnavailabilityIndicatorsReset(opts *bind.FilterOpts) (*SlashIndicatorUnavailabilityIndicatorsResetIterator, error) { +// Solidity: event FelonyJailDurationUpdated(uint256 felonyJailDuration) +func (_SlashIndicator *SlashIndicatorFilterer) FilterFelonyJailDurationUpdated(opts *bind.FilterOpts) (*SlashIndicatorFelonyJailDurationUpdatedIterator, error) { - logs, sub, err := _SlashIndicator.contract.FilterLogs(opts, "UnavailabilityIndicatorsReset") + logs, sub, err := _SlashIndicator.contract.FilterLogs(opts, "FelonyJailDurationUpdated") if err != nil { return nil, err } - return &SlashIndicatorUnavailabilityIndicatorsResetIterator{contract: _SlashIndicator.contract, event: "UnavailabilityIndicatorsReset", logs: logs, sub: sub}, nil + return &SlashIndicatorFelonyJailDurationUpdatedIterator{contract: _SlashIndicator.contract, event: "FelonyJailDurationUpdated", logs: logs, sub: sub}, nil } -// WatchUnavailabilityIndicatorsReset is a free log subscription operation binding the contract event 0x9ae71e4f83d6019cd988ca4c38a696d015d5f6e41f3fd708fb746d2b672b4996. +// WatchFelonyJailDurationUpdated is a free log subscription operation binding the contract event 0x3092a623ebcf71b79f9f68801b081a4d0c839dfb4c0e6f9ff118f4fb870375dc. // -// Solidity: event UnavailabilityIndicatorsReset(address[] validators) -func (_SlashIndicator *SlashIndicatorFilterer) WatchUnavailabilityIndicatorsReset(opts *bind.WatchOpts, sink chan<- *SlashIndicatorUnavailabilityIndicatorsReset) (event.Subscription, error) { +// Solidity: event FelonyJailDurationUpdated(uint256 felonyJailDuration) +func (_SlashIndicator *SlashIndicatorFilterer) WatchFelonyJailDurationUpdated(opts *bind.WatchOpts, sink chan<- *SlashIndicatorFelonyJailDurationUpdated) (event.Subscription, error) { - logs, sub, err := _SlashIndicator.contract.WatchLogs(opts, "UnavailabilityIndicatorsReset") + logs, sub, err := _SlashIndicator.contract.WatchLogs(opts, "FelonyJailDurationUpdated") if err != nil { return nil, err } @@ -551,8 +908,8 @@ func (_SlashIndicator *SlashIndicatorFilterer) WatchUnavailabilityIndicatorsRese select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(SlashIndicatorUnavailabilityIndicatorsReset) - if err := _SlashIndicator.contract.UnpackLog(event, "UnavailabilityIndicatorsReset", log); err != nil { + event := new(SlashIndicatorFelonyJailDurationUpdated) + if err := _SlashIndicator.contract.UnpackLog(event, "FelonyJailDurationUpdated", log); err != nil { return err } event.Raw = log @@ -573,21 +930,21 @@ func (_SlashIndicator *SlashIndicatorFilterer) WatchUnavailabilityIndicatorsRese }), nil } -// ParseUnavailabilityIndicatorsReset is a log parse operation binding the contract event 0x9ae71e4f83d6019cd988ca4c38a696d015d5f6e41f3fd708fb746d2b672b4996. +// ParseFelonyJailDurationUpdated is a log parse operation binding the contract event 0x3092a623ebcf71b79f9f68801b081a4d0c839dfb4c0e6f9ff118f4fb870375dc. // -// Solidity: event UnavailabilityIndicatorsReset(address[] validators) -func (_SlashIndicator *SlashIndicatorFilterer) ParseUnavailabilityIndicatorsReset(log types.Log) (*SlashIndicatorUnavailabilityIndicatorsReset, error) { - event := new(SlashIndicatorUnavailabilityIndicatorsReset) - if err := _SlashIndicator.contract.UnpackLog(event, "UnavailabilityIndicatorsReset", log); err != nil { +// Solidity: event FelonyJailDurationUpdated(uint256 felonyJailDuration) +func (_SlashIndicator *SlashIndicatorFilterer) ParseFelonyJailDurationUpdated(log types.Log) (*SlashIndicatorFelonyJailDurationUpdated, error) { + event := new(SlashIndicatorFelonyJailDurationUpdated) + if err := _SlashIndicator.contract.UnpackLog(event, "FelonyJailDurationUpdated", log); err != nil { return nil, err } event.Raw = log return event, nil } -// SlashIndicatorValidatorSlashedIterator is returned from FilterValidatorSlashed and is used to iterate over the raw logs and unpacked data for ValidatorSlashed events raised by the SlashIndicator contract. -type SlashIndicatorValidatorSlashedIterator struct { - Event *SlashIndicatorValidatorSlashed // Event containing the contract specifics and raw log +// SlashIndicatorInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the SlashIndicator contract. +type SlashIndicatorInitializedIterator struct { + Event *SlashIndicatorInitialized // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -601,7 +958,7 @@ type SlashIndicatorValidatorSlashedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *SlashIndicatorValidatorSlashedIterator) Next() bool { +func (it *SlashIndicatorInitializedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -610,7 +967,7 @@ func (it *SlashIndicatorValidatorSlashedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(SlashIndicatorValidatorSlashed) + it.Event = new(SlashIndicatorInitialized) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -625,7 +982,7 @@ func (it *SlashIndicatorValidatorSlashedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(SlashIndicatorValidatorSlashed) + it.Event = new(SlashIndicatorInitialized) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -641,52 +998,858 @@ func (it *SlashIndicatorValidatorSlashedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *SlashIndicatorValidatorSlashedIterator) Error() error { +func (it *SlashIndicatorInitializedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *SlashIndicatorValidatorSlashedIterator) Close() error { +func (it *SlashIndicatorInitializedIterator) Close() error { it.sub.Unsubscribe() return nil } -// SlashIndicatorValidatorSlashed represents a ValidatorSlashed event raised by the SlashIndicator contract. -type SlashIndicatorValidatorSlashed struct { - Validator common.Address - SlashType uint8 - Raw types.Log // Blockchain specific contextual infos +// SlashIndicatorInitialized represents a Initialized event raised by the SlashIndicator contract. +type SlashIndicatorInitialized struct { + Version uint8 + Raw types.Log // Blockchain specific contextual infos } -// FilterValidatorSlashed is a free log retrieval operation binding the contract event 0x72b4cbc6db714fd31d4f3a8686c34df7b11819178ea38a792798f38a99d15e4a. +// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. // -// Solidity: event ValidatorSlashed(address indexed validator, uint8 slashType) -func (_SlashIndicator *SlashIndicatorFilterer) FilterValidatorSlashed(opts *bind.FilterOpts, validator []common.Address) (*SlashIndicatorValidatorSlashedIterator, error) { +// Solidity: event Initialized(uint8 version) +func (_SlashIndicator *SlashIndicatorFilterer) FilterInitialized(opts *bind.FilterOpts) (*SlashIndicatorInitializedIterator, error) { - var validatorRule []interface{} - for _, validatorItem := range validator { - validatorRule = append(validatorRule, validatorItem) + logs, sub, err := _SlashIndicator.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err } + return &SlashIndicatorInitializedIterator{contract: _SlashIndicator.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_SlashIndicator *SlashIndicatorFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *SlashIndicatorInitialized) (event.Subscription, error) { - logs, sub, err := _SlashIndicator.contract.FilterLogs(opts, "ValidatorSlashed", validatorRule) + logs, sub, err := _SlashIndicator.contract.WatchLogs(opts, "Initialized") if err != nil { return nil, err } - return &SlashIndicatorValidatorSlashedIterator{contract: _SlashIndicator.contract, event: "ValidatorSlashed", logs: logs, sub: sub}, nil + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(SlashIndicatorInitialized) + if err := _SlashIndicator.contract.UnpackLog(event, "Initialized", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil } -// WatchValidatorSlashed is a free log subscription operation binding the contract event 0x72b4cbc6db714fd31d4f3a8686c34df7b11819178ea38a792798f38a99d15e4a. +// ParseInitialized is a log parse operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. // -// Solidity: event ValidatorSlashed(address indexed validator, uint8 slashType) -func (_SlashIndicator *SlashIndicatorFilterer) WatchValidatorSlashed(opts *bind.WatchOpts, sink chan<- *SlashIndicatorValidatorSlashed, validator []common.Address) (event.Subscription, error) { +// Solidity: event Initialized(uint8 version) +func (_SlashIndicator *SlashIndicatorFilterer) ParseInitialized(log types.Log) (*SlashIndicatorInitialized, error) { + event := new(SlashIndicatorInitialized) + if err := _SlashIndicator.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} - var validatorRule []interface{} - for _, validatorItem := range validator { - validatorRule = append(validatorRule, validatorItem) +// SlashIndicatorMaintenanceContractUpdatedIterator is returned from FilterMaintenanceContractUpdated and is used to iterate over the raw logs and unpacked data for MaintenanceContractUpdated events raised by the SlashIndicator contract. +type SlashIndicatorMaintenanceContractUpdatedIterator struct { + Event *SlashIndicatorMaintenanceContractUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *SlashIndicatorMaintenanceContractUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(SlashIndicatorMaintenanceContractUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(SlashIndicatorMaintenanceContractUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *SlashIndicatorMaintenanceContractUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *SlashIndicatorMaintenanceContractUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// SlashIndicatorMaintenanceContractUpdated represents a MaintenanceContractUpdated event raised by the SlashIndicator contract. +type SlashIndicatorMaintenanceContractUpdated struct { + Arg0 common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterMaintenanceContractUpdated is a free log retrieval operation binding the contract event 0x31a33f126a5bae3c5bdf6cfc2cd6dcfffe2fe9634bdb09e21c44762993889e3b. +// +// Solidity: event MaintenanceContractUpdated(address arg0) +func (_SlashIndicator *SlashIndicatorFilterer) FilterMaintenanceContractUpdated(opts *bind.FilterOpts) (*SlashIndicatorMaintenanceContractUpdatedIterator, error) { + + logs, sub, err := _SlashIndicator.contract.FilterLogs(opts, "MaintenanceContractUpdated") + if err != nil { + return nil, err + } + return &SlashIndicatorMaintenanceContractUpdatedIterator{contract: _SlashIndicator.contract, event: "MaintenanceContractUpdated", logs: logs, sub: sub}, nil +} + +// WatchMaintenanceContractUpdated is a free log subscription operation binding the contract event 0x31a33f126a5bae3c5bdf6cfc2cd6dcfffe2fe9634bdb09e21c44762993889e3b. +// +// Solidity: event MaintenanceContractUpdated(address arg0) +func (_SlashIndicator *SlashIndicatorFilterer) WatchMaintenanceContractUpdated(opts *bind.WatchOpts, sink chan<- *SlashIndicatorMaintenanceContractUpdated) (event.Subscription, error) { + + logs, sub, err := _SlashIndicator.contract.WatchLogs(opts, "MaintenanceContractUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(SlashIndicatorMaintenanceContractUpdated) + if err := _SlashIndicator.contract.UnpackLog(event, "MaintenanceContractUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseMaintenanceContractUpdated is a log parse operation binding the contract event 0x31a33f126a5bae3c5bdf6cfc2cd6dcfffe2fe9634bdb09e21c44762993889e3b. +// +// Solidity: event MaintenanceContractUpdated(address arg0) +func (_SlashIndicator *SlashIndicatorFilterer) ParseMaintenanceContractUpdated(log types.Log) (*SlashIndicatorMaintenanceContractUpdated, error) { + event := new(SlashIndicatorMaintenanceContractUpdated) + if err := _SlashIndicator.contract.UnpackLog(event, "MaintenanceContractUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// SlashIndicatorSlashDoubleSignAmountUpdatedIterator is returned from FilterSlashDoubleSignAmountUpdated and is used to iterate over the raw logs and unpacked data for SlashDoubleSignAmountUpdated events raised by the SlashIndicator contract. +type SlashIndicatorSlashDoubleSignAmountUpdatedIterator struct { + Event *SlashIndicatorSlashDoubleSignAmountUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *SlashIndicatorSlashDoubleSignAmountUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(SlashIndicatorSlashDoubleSignAmountUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(SlashIndicatorSlashDoubleSignAmountUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *SlashIndicatorSlashDoubleSignAmountUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *SlashIndicatorSlashDoubleSignAmountUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// SlashIndicatorSlashDoubleSignAmountUpdated represents a SlashDoubleSignAmountUpdated event raised by the SlashIndicator contract. +type SlashIndicatorSlashDoubleSignAmountUpdated struct { + SlashDoubleSignAmount *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterSlashDoubleSignAmountUpdated is a free log retrieval operation binding the contract event 0x42458d43c99c17f034dde22f3a1cf003e4bc27372c1ff14cb9e68a79a1b1e8ed. +// +// Solidity: event SlashDoubleSignAmountUpdated(uint256 slashDoubleSignAmount) +func (_SlashIndicator *SlashIndicatorFilterer) FilterSlashDoubleSignAmountUpdated(opts *bind.FilterOpts) (*SlashIndicatorSlashDoubleSignAmountUpdatedIterator, error) { + + logs, sub, err := _SlashIndicator.contract.FilterLogs(opts, "SlashDoubleSignAmountUpdated") + if err != nil { + return nil, err + } + return &SlashIndicatorSlashDoubleSignAmountUpdatedIterator{contract: _SlashIndicator.contract, event: "SlashDoubleSignAmountUpdated", logs: logs, sub: sub}, nil +} + +// WatchSlashDoubleSignAmountUpdated is a free log subscription operation binding the contract event 0x42458d43c99c17f034dde22f3a1cf003e4bc27372c1ff14cb9e68a79a1b1e8ed. +// +// Solidity: event SlashDoubleSignAmountUpdated(uint256 slashDoubleSignAmount) +func (_SlashIndicator *SlashIndicatorFilterer) WatchSlashDoubleSignAmountUpdated(opts *bind.WatchOpts, sink chan<- *SlashIndicatorSlashDoubleSignAmountUpdated) (event.Subscription, error) { + + logs, sub, err := _SlashIndicator.contract.WatchLogs(opts, "SlashDoubleSignAmountUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(SlashIndicatorSlashDoubleSignAmountUpdated) + if err := _SlashIndicator.contract.UnpackLog(event, "SlashDoubleSignAmountUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseSlashDoubleSignAmountUpdated is a log parse operation binding the contract event 0x42458d43c99c17f034dde22f3a1cf003e4bc27372c1ff14cb9e68a79a1b1e8ed. +// +// Solidity: event SlashDoubleSignAmountUpdated(uint256 slashDoubleSignAmount) +func (_SlashIndicator *SlashIndicatorFilterer) ParseSlashDoubleSignAmountUpdated(log types.Log) (*SlashIndicatorSlashDoubleSignAmountUpdated, error) { + event := new(SlashIndicatorSlashDoubleSignAmountUpdated) + if err := _SlashIndicator.contract.UnpackLog(event, "SlashDoubleSignAmountUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// SlashIndicatorSlashFelonyAmountUpdatedIterator is returned from FilterSlashFelonyAmountUpdated and is used to iterate over the raw logs and unpacked data for SlashFelonyAmountUpdated events raised by the SlashIndicator contract. +type SlashIndicatorSlashFelonyAmountUpdatedIterator struct { + Event *SlashIndicatorSlashFelonyAmountUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *SlashIndicatorSlashFelonyAmountUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(SlashIndicatorSlashFelonyAmountUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(SlashIndicatorSlashFelonyAmountUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *SlashIndicatorSlashFelonyAmountUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *SlashIndicatorSlashFelonyAmountUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// SlashIndicatorSlashFelonyAmountUpdated represents a SlashFelonyAmountUpdated event raised by the SlashIndicator contract. +type SlashIndicatorSlashFelonyAmountUpdated struct { + SlashFelonyAmount *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterSlashFelonyAmountUpdated is a free log retrieval operation binding the contract event 0x71491762d43dbadd94f85cf7a0322192a7c22f3ca4fb30de8895420607b56712. +// +// Solidity: event SlashFelonyAmountUpdated(uint256 slashFelonyAmount) +func (_SlashIndicator *SlashIndicatorFilterer) FilterSlashFelonyAmountUpdated(opts *bind.FilterOpts) (*SlashIndicatorSlashFelonyAmountUpdatedIterator, error) { + + logs, sub, err := _SlashIndicator.contract.FilterLogs(opts, "SlashFelonyAmountUpdated") + if err != nil { + return nil, err + } + return &SlashIndicatorSlashFelonyAmountUpdatedIterator{contract: _SlashIndicator.contract, event: "SlashFelonyAmountUpdated", logs: logs, sub: sub}, nil +} + +// WatchSlashFelonyAmountUpdated is a free log subscription operation binding the contract event 0x71491762d43dbadd94f85cf7a0322192a7c22f3ca4fb30de8895420607b56712. +// +// Solidity: event SlashFelonyAmountUpdated(uint256 slashFelonyAmount) +func (_SlashIndicator *SlashIndicatorFilterer) WatchSlashFelonyAmountUpdated(opts *bind.WatchOpts, sink chan<- *SlashIndicatorSlashFelonyAmountUpdated) (event.Subscription, error) { + + logs, sub, err := _SlashIndicator.contract.WatchLogs(opts, "SlashFelonyAmountUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(SlashIndicatorSlashFelonyAmountUpdated) + if err := _SlashIndicator.contract.UnpackLog(event, "SlashFelonyAmountUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseSlashFelonyAmountUpdated is a log parse operation binding the contract event 0x71491762d43dbadd94f85cf7a0322192a7c22f3ca4fb30de8895420607b56712. +// +// Solidity: event SlashFelonyAmountUpdated(uint256 slashFelonyAmount) +func (_SlashIndicator *SlashIndicatorFilterer) ParseSlashFelonyAmountUpdated(log types.Log) (*SlashIndicatorSlashFelonyAmountUpdated, error) { + event := new(SlashIndicatorSlashFelonyAmountUpdated) + if err := _SlashIndicator.contract.UnpackLog(event, "SlashFelonyAmountUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// SlashIndicatorSlashThresholdsUpdatedIterator is returned from FilterSlashThresholdsUpdated and is used to iterate over the raw logs and unpacked data for SlashThresholdsUpdated events raised by the SlashIndicator contract. +type SlashIndicatorSlashThresholdsUpdatedIterator struct { + Event *SlashIndicatorSlashThresholdsUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *SlashIndicatorSlashThresholdsUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(SlashIndicatorSlashThresholdsUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(SlashIndicatorSlashThresholdsUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *SlashIndicatorSlashThresholdsUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *SlashIndicatorSlashThresholdsUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// SlashIndicatorSlashThresholdsUpdated represents a SlashThresholdsUpdated event raised by the SlashIndicator contract. +type SlashIndicatorSlashThresholdsUpdated struct { + FelonyThreshold *big.Int + MisdemeanorThreshold *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterSlashThresholdsUpdated is a free log retrieval operation binding the contract event 0x25a70459f14137ea646efb17b806c2e75632b931d69e642a8a809b6bfd7217a6. +// +// Solidity: event SlashThresholdsUpdated(uint256 felonyThreshold, uint256 misdemeanorThreshold) +func (_SlashIndicator *SlashIndicatorFilterer) FilterSlashThresholdsUpdated(opts *bind.FilterOpts) (*SlashIndicatorSlashThresholdsUpdatedIterator, error) { + + logs, sub, err := _SlashIndicator.contract.FilterLogs(opts, "SlashThresholdsUpdated") + if err != nil { + return nil, err + } + return &SlashIndicatorSlashThresholdsUpdatedIterator{contract: _SlashIndicator.contract, event: "SlashThresholdsUpdated", logs: logs, sub: sub}, nil +} + +// WatchSlashThresholdsUpdated is a free log subscription operation binding the contract event 0x25a70459f14137ea646efb17b806c2e75632b931d69e642a8a809b6bfd7217a6. +// +// Solidity: event SlashThresholdsUpdated(uint256 felonyThreshold, uint256 misdemeanorThreshold) +func (_SlashIndicator *SlashIndicatorFilterer) WatchSlashThresholdsUpdated(opts *bind.WatchOpts, sink chan<- *SlashIndicatorSlashThresholdsUpdated) (event.Subscription, error) { + + logs, sub, err := _SlashIndicator.contract.WatchLogs(opts, "SlashThresholdsUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(SlashIndicatorSlashThresholdsUpdated) + if err := _SlashIndicator.contract.UnpackLog(event, "SlashThresholdsUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseSlashThresholdsUpdated is a log parse operation binding the contract event 0x25a70459f14137ea646efb17b806c2e75632b931d69e642a8a809b6bfd7217a6. +// +// Solidity: event SlashThresholdsUpdated(uint256 felonyThreshold, uint256 misdemeanorThreshold) +func (_SlashIndicator *SlashIndicatorFilterer) ParseSlashThresholdsUpdated(log types.Log) (*SlashIndicatorSlashThresholdsUpdated, error) { + event := new(SlashIndicatorSlashThresholdsUpdated) + if err := _SlashIndicator.contract.UnpackLog(event, "SlashThresholdsUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// SlashIndicatorUnavailabilitySlashedIterator is returned from FilterUnavailabilitySlashed and is used to iterate over the raw logs and unpacked data for UnavailabilitySlashed events raised by the SlashIndicator contract. +type SlashIndicatorUnavailabilitySlashedIterator struct { + Event *SlashIndicatorUnavailabilitySlashed // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *SlashIndicatorUnavailabilitySlashedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(SlashIndicatorUnavailabilitySlashed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(SlashIndicatorUnavailabilitySlashed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *SlashIndicatorUnavailabilitySlashedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *SlashIndicatorUnavailabilitySlashedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// SlashIndicatorUnavailabilitySlashed represents a UnavailabilitySlashed event raised by the SlashIndicator contract. +type SlashIndicatorUnavailabilitySlashed struct { + Validator common.Address + SlashType uint8 + Period *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUnavailabilitySlashed is a free log retrieval operation binding the contract event 0x8c2c2bfe532ccdb4523fa2392954fd58445929e7f260d786d0ab93cd981cde54. +// +// Solidity: event UnavailabilitySlashed(address indexed validator, uint8 slashType, uint256 period) +func (_SlashIndicator *SlashIndicatorFilterer) FilterUnavailabilitySlashed(opts *bind.FilterOpts, validator []common.Address) (*SlashIndicatorUnavailabilitySlashedIterator, error) { + + var validatorRule []interface{} + for _, validatorItem := range validator { + validatorRule = append(validatorRule, validatorItem) + } + + logs, sub, err := _SlashIndicator.contract.FilterLogs(opts, "UnavailabilitySlashed", validatorRule) + if err != nil { + return nil, err + } + return &SlashIndicatorUnavailabilitySlashedIterator{contract: _SlashIndicator.contract, event: "UnavailabilitySlashed", logs: logs, sub: sub}, nil +} + +// WatchUnavailabilitySlashed is a free log subscription operation binding the contract event 0x8c2c2bfe532ccdb4523fa2392954fd58445929e7f260d786d0ab93cd981cde54. +// +// Solidity: event UnavailabilitySlashed(address indexed validator, uint8 slashType, uint256 period) +func (_SlashIndicator *SlashIndicatorFilterer) WatchUnavailabilitySlashed(opts *bind.WatchOpts, sink chan<- *SlashIndicatorUnavailabilitySlashed, validator []common.Address) (event.Subscription, error) { + + var validatorRule []interface{} + for _, validatorItem := range validator { + validatorRule = append(validatorRule, validatorItem) + } + + logs, sub, err := _SlashIndicator.contract.WatchLogs(opts, "UnavailabilitySlashed", validatorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(SlashIndicatorUnavailabilitySlashed) + if err := _SlashIndicator.contract.UnpackLog(event, "UnavailabilitySlashed", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseUnavailabilitySlashed is a log parse operation binding the contract event 0x8c2c2bfe532ccdb4523fa2392954fd58445929e7f260d786d0ab93cd981cde54. +// +// Solidity: event UnavailabilitySlashed(address indexed validator, uint8 slashType, uint256 period) +func (_SlashIndicator *SlashIndicatorFilterer) ParseUnavailabilitySlashed(log types.Log) (*SlashIndicatorUnavailabilitySlashed, error) { + event := new(SlashIndicatorUnavailabilitySlashed) + if err := _SlashIndicator.contract.UnpackLog(event, "UnavailabilitySlashed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// SlashIndicatorValidatorContractUpdatedIterator is returned from FilterValidatorContractUpdated and is used to iterate over the raw logs and unpacked data for ValidatorContractUpdated events raised by the SlashIndicator contract. +type SlashIndicatorValidatorContractUpdatedIterator struct { + Event *SlashIndicatorValidatorContractUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *SlashIndicatorValidatorContractUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(SlashIndicatorValidatorContractUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(SlashIndicatorValidatorContractUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *SlashIndicatorValidatorContractUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *SlashIndicatorValidatorContractUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// SlashIndicatorValidatorContractUpdated represents a ValidatorContractUpdated event raised by the SlashIndicator contract. +type SlashIndicatorValidatorContractUpdated struct { + Arg0 common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterValidatorContractUpdated is a free log retrieval operation binding the contract event 0xef40dc07567635f84f5edbd2f8dbc16b40d9d282dd8e7e6f4ff58236b6836169. +// +// Solidity: event ValidatorContractUpdated(address arg0) +func (_SlashIndicator *SlashIndicatorFilterer) FilterValidatorContractUpdated(opts *bind.FilterOpts) (*SlashIndicatorValidatorContractUpdatedIterator, error) { + + logs, sub, err := _SlashIndicator.contract.FilterLogs(opts, "ValidatorContractUpdated") + if err != nil { + return nil, err + } + return &SlashIndicatorValidatorContractUpdatedIterator{contract: _SlashIndicator.contract, event: "ValidatorContractUpdated", logs: logs, sub: sub}, nil +} + +// WatchValidatorContractUpdated is a free log subscription operation binding the contract event 0xef40dc07567635f84f5edbd2f8dbc16b40d9d282dd8e7e6f4ff58236b6836169. +// +// Solidity: event ValidatorContractUpdated(address arg0) +func (_SlashIndicator *SlashIndicatorFilterer) WatchValidatorContractUpdated(opts *bind.WatchOpts, sink chan<- *SlashIndicatorValidatorContractUpdated) (event.Subscription, error) { - logs, sub, err := _SlashIndicator.contract.WatchLogs(opts, "ValidatorSlashed", validatorRule) + logs, sub, err := _SlashIndicator.contract.WatchLogs(opts, "ValidatorContractUpdated") if err != nil { return nil, err } @@ -696,8 +1859,8 @@ func (_SlashIndicator *SlashIndicatorFilterer) WatchValidatorSlashed(opts *bind. select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(SlashIndicatorValidatorSlashed) - if err := _SlashIndicator.contract.UnpackLog(event, "ValidatorSlashed", log); err != nil { + event := new(SlashIndicatorValidatorContractUpdated) + if err := _SlashIndicator.contract.UnpackLog(event, "ValidatorContractUpdated", log); err != nil { return err } event.Raw = log @@ -718,12 +1881,12 @@ func (_SlashIndicator *SlashIndicatorFilterer) WatchValidatorSlashed(opts *bind. }), nil } -// ParseValidatorSlashed is a log parse operation binding the contract event 0x72b4cbc6db714fd31d4f3a8686c34df7b11819178ea38a792798f38a99d15e4a. +// ParseValidatorContractUpdated is a log parse operation binding the contract event 0xef40dc07567635f84f5edbd2f8dbc16b40d9d282dd8e7e6f4ff58236b6836169. // -// Solidity: event ValidatorSlashed(address indexed validator, uint8 slashType) -func (_SlashIndicator *SlashIndicatorFilterer) ParseValidatorSlashed(log types.Log) (*SlashIndicatorValidatorSlashed, error) { - event := new(SlashIndicatorValidatorSlashed) - if err := _SlashIndicator.contract.UnpackLog(event, "ValidatorSlashed", log); err != nil { +// Solidity: event ValidatorContractUpdated(address arg0) +func (_SlashIndicator *SlashIndicatorFilterer) ParseValidatorContractUpdated(log types.Log) (*SlashIndicatorValidatorContractUpdated, error) { + event := new(SlashIndicatorValidatorContractUpdated) + if err := _SlashIndicator.contract.UnpackLog(event, "ValidatorContractUpdated", log); err != nil { return nil, err } event.Raw = log From 3af09575260f975416d5090335e01711351ca680 Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Thu, 29 Sep 2022 13:38:05 +0700 Subject: [PATCH 38/52] fix: gas limit is not enough when call WrapUp (#135) --- consensus/consortium/common/contract.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/consensus/consortium/common/contract.go b/consensus/consortium/common/contract.go index 94d0d5afc4..d54700b4f0 100644 --- a/consensus/consortium/common/contract.go +++ b/consensus/consortium/common/contract.go @@ -32,7 +32,7 @@ var errMethodUnimplemented = errors.New("method is unimplemented") func getTransactionOpts(from common.Address, nonce uint64, chainId *big.Int, signTxFn SignerTxFn) *bind.TransactOpts { return &bind.TransactOpts{ From: from, - GasLimit: 1000000, + GasLimit: uint64(math.MaxUint64 / 2), GasPrice: big.NewInt(0), // Set dummy value always equal 0 since it will be overridden when creating a new message Value: new(big.Int).SetUint64(0), @@ -243,6 +243,7 @@ func ApplyTransaction(msg types.Message, opts *ApplyTransactOpts) (err error) { } opts.State.Prepare(expectedTx.Hash(), len(*txs)) gasUsed, err := applyMessage(msg, opts.ApplyMessageOpts) + log.Debug("ApplyTransaction", "gasUsed", gasUsed) if err != nil { return err } From 25dbc170b9bd66e93608790dbd8b610014ae1781 Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Thu, 29 Sep 2022 13:38:16 +0700 Subject: [PATCH 39/52] fix: race condition while updating precompiles list (#136) --- core/vm/evm.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index 082cef5526..8619e0ae42 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -61,16 +61,21 @@ func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { return &blacklistedAddress{}, true } - var precompiles map[common.Address]PrecompiledContract + var precompiles, tmpPrecompiles map[common.Address]PrecompiledContract + // add eth precompile contracts switch { case evm.chainRules.IsBerlin: - precompiles = PrecompiledContractsBerlin + tmpPrecompiles = PrecompiledContractsBerlin case evm.chainRules.IsIstanbul: - precompiles = PrecompiledContractsIstanbul + tmpPrecompiles = PrecompiledContractsIstanbul case evm.chainRules.IsByzantium: - precompiles = PrecompiledContractsByzantium + tmpPrecompiles = PrecompiledContractsByzantium default: - precompiles = PrecompiledContractsHomestead + tmpPrecompiles = PrecompiledContractsHomestead + } + + for address, contract := range tmpPrecompiles { + precompiles[address] = contract } // add consortium precompiled contracts to list From 8352824860c93e8d371b22a2f672fb7441b995a8 Mon Sep 17 00:00:00 2001 From: minh-bq <97180373+minh-bq@users.noreply.github.com> Date: Thu, 29 Sep 2022 13:52:25 +0700 Subject: [PATCH 40/52] Init precompile map before assigning elements (#137) --- core/vm/evm.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index 8619e0ae42..a9ca395747 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -61,7 +61,7 @@ func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { return &blacklistedAddress{}, true } - var precompiles, tmpPrecompiles map[common.Address]PrecompiledContract + var tmpPrecompiles map[common.Address]PrecompiledContract // add eth precompile contracts switch { case evm.chainRules.IsBerlin: @@ -74,6 +74,7 @@ func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { tmpPrecompiles = PrecompiledContractsHomestead } + precompiles := make(map[common.Address]PrecompiledContract) for address, contract := range tmpPrecompiles { precompiles[address] = contract } From 0eea767f0f8df1e8848023bb03fe8d983e120277 Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Mon, 3 Oct 2022 11:49:41 +0700 Subject: [PATCH 41/52] feat: Implement `sortValidators` precompiled contract (#138) * feat: Implement `sortValidators` precompiled contract * fix: add caller to the contract, since caller is the actual caller instead of sender from transaction * chore: add testcase which simulates a call from a user who trigger system contract to call `sort` precompiled contract * fix: incorrect get validators function should be `getValidatorCandidates` instead --- core/vm/consortium_precompiled_contracts.go | 196 +++++++++++++ .../consortium_precompiled_contracts_test.go | 272 ++++++++++++++++++ core/vm/contracts.go | 62 +--- core/vm/evm.go | 12 +- params/config.go | 1 + 5 files changed, 480 insertions(+), 63 deletions(-) create mode 100644 core/vm/consortium_precompiled_contracts.go create mode 100644 core/vm/consortium_precompiled_contracts_test.go diff --git a/core/vm/consortium_precompiled_contracts.go b/core/vm/consortium_precompiled_contracts.go new file mode 100644 index 0000000000..2325f4b500 --- /dev/null +++ b/core/vm/consortium_precompiled_contracts.go @@ -0,0 +1,196 @@ +package vm + +import ( + "errors" + "fmt" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/log" + "math/big" + "math/rand" + "os" + "strings" +) + +var ( + consortiumLogAbi = `[{"inputs":[{"internalType":"string","name":"message","type":"string"}],"name":"log","outputs":[],"stateMutability":"nonpayable","type":"function"}]` + consortiumSortValidatorAbi = `[{"inputs":[],"name":"getValidatorCandidates","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"sortValidators","outputs":[{"internalType":"address[]","name":"validators","type":"address[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_poolList","type":"address[]"}],"name":"totalBalances","outputs":[{"internalType":"uint256[]","name":"_balances","type":"uint256[]"}],"stateMutability":"view","type":"function"}]` +) + +const ( + sortValidatorsMethod = "sortValidators" + logMethod = "log" + getValidatorsMethod = "getValidatorCandidates" + totalBalancesMethod = "totalBalances" +) + +func PrecompiledContractsConsortium(caller ContractRef, evm *EVM) map[common.Address]PrecompiledContract { + return map[common.Address]PrecompiledContract{ + common.BytesToAddress([]byte{101}): &consortiumLog{}, + common.BytesToAddress([]byte{102}): &consortiumValidatorSorting{caller: caller, evm: evm}, + } +} + +type consortiumLog struct{} + +func (c *consortiumLog) RequiredGas(input []byte) uint64 { + return 0 +} + +func (c *consortiumLog) Run(input []byte) ([]byte, error) { + if os.Getenv("DEBUG") != "true" { + return input, nil + } + _, method, args, err := loadMethodAndArgs(consortiumLogAbi, input) + if err != nil { + return nil, err + } + switch method.Name { + case logMethod: + if len(args) == 0 { + return input, nil + } + if _, ok := args[0].(string); ok { + log.Info("[consortiumLog] log message from smart contract", "message", args[0].(string)) + } + } + return input, nil +} + +type consortiumValidatorSorting struct { + caller ContractRef + evm *EVM +} + +func (c *consortiumValidatorSorting) RequiredGas(input []byte) uint64 { + return 0 +} + +func (c *consortiumValidatorSorting) Run(input []byte) ([]byte, error) { + if c.evm.ChainConfig().ConsortiumV2Contracts == nil { + return nil, errors.New("cannot find consortium v2 contracts") + } + if !c.evm.ChainConfig().ConsortiumV2Contracts.IsSystemContract(c.caller.Address()) { + return nil, errors.New("unauthorized sender") + } + // get method, args from abi + smcAbi, method, args, err := loadMethodAndArgs(consortiumSortValidatorAbi, input) + if err != nil { + return nil, err + } + if method.Name != sortValidatorsMethod { + return nil, errors.New("invalid method") + } + if len(args) != 1 { + return nil, errors.New(fmt.Sprintf("invalid arguments, expected 1 got %d", len(args))) + } + // cast args[0] to number + limit, ok := args[0].(*big.Int) + if !ok { + return nil, errors.New("invalid argument type") + } + validators, err := loadValidators(c.evm, smcAbi, c.caller.Address()) + if err != nil { + return nil, err + } + totalBalances, err := loadTotalBalances(c.evm, smcAbi, c.caller.Address(), validators) + if err != nil { + return nil, err + } + if len(validators) != len(totalBalances) { + return nil, errors.New("balances and validators length mismatched") + } + sortValidators(validators, totalBalances) + + if limit.Int64() > int64(len(validators)) { + limit = big.NewInt(int64(len(validators))) + } + + return method.Outputs.Pack(validators[:limit.Int64()]) +} + +func sortValidators(validators []common.Address, balances []*big.Int) { + if len(validators) < 2 { + return + } + + left, right := 0, len(validators)-1 + + pivot := rand.Int() % len(validators) + + validators[pivot], validators[right] = validators[right], validators[pivot] + balances[pivot], balances[right] = balances[right], balances[pivot] + + for i, _ := range validators { + cmp := balances[i].Cmp(balances[right]) + addrsCmp := big.NewInt(0).SetBytes(validators[i].Bytes()).Cmp(big.NewInt(0).SetBytes(validators[right].Bytes())) > 0 + if cmp > 0 || (cmp == 0 && addrsCmp) { + validators[left], validators[i] = validators[i], validators[left] + balances[left], balances[i] = balances[i], balances[left] + left++ + } + } + + validators[left], validators[right] = validators[right], validators[left] + balances[left], balances[right] = balances[right], balances[left] + + sortValidators(validators[:left], balances[:left]) + sortValidators(validators[left+1:], balances[left+1:]) + + return +} + +func loadValidators(evm *EVM, smcAbi abi.ABI, sender common.Address) ([]common.Address, error) { + res, err := staticCall(evm, smcAbi, getValidatorsMethod, evm.ChainConfig().ConsortiumV2Contracts.RoninValidatorSet, sender) + if err != nil { + return nil, err + } + return *abi.ConvertType(res[0], new([]common.Address)).(*[]common.Address), nil +} + +func loadTotalBalances(evm *EVM, smcAbi abi.ABI, sender common.Address, validators []common.Address) ([]*big.Int, error) { + res, err := staticCall(evm, smcAbi, totalBalancesMethod, evm.ChainConfig().ConsortiumV2Contracts.StakingContract, sender, validators) + if err != nil { + return nil, err + } + return *abi.ConvertType(res[0], new([]*big.Int)).(*[]*big.Int), nil +} + +func staticCall(evm *EVM, smcAbi abi.ABI, method string, contract, sender common.Address, args ...interface{}) ([]interface{}, error) { + inputParams, err := smcAbi.Pack(method, args...) + if err != nil { + return nil, err + } + ret, _, err := evm.StaticCall(AccountRef(sender), contract, inputParams, math.MaxUint64/2) + if err != nil { + return nil, err + } + out, err := smcAbi.Unpack(method, ret) + if err != nil { + return nil, err + } + if len(out) == 0 { + return nil, errors.New("data not found") + } + return out, nil +} + +func loadMethodAndArgs(smcAbi string, input []byte) (abi.ABI, *abi.Method, []interface{}, error) { + var ( + pAbi abi.ABI + err error + method *abi.Method + args []interface{} + ) + if pAbi, err = abi.JSON(strings.NewReader(smcAbi)); err != nil { + return abi.ABI{}, nil, nil, err + } + if method, err = pAbi.MethodById(input); err != nil { + return abi.ABI{}, nil, nil, err + } + if args, err = method.Inputs.Unpack(input[4:]); err != nil { + return abi.ABI{}, nil, nil, err + } + return pAbi, method, args, nil +} diff --git a/core/vm/consortium_precompiled_contracts_test.go b/core/vm/consortium_precompiled_contracts_test.go new file mode 100644 index 0000000000..c12a800b74 --- /dev/null +++ b/core/vm/consortium_precompiled_contracts_test.go @@ -0,0 +1,272 @@ +package vm + +import ( + "fmt" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/params" + "math/big" + "strings" + "testing" +) + +/** +testSortCodes is generated based on the following code +``` +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity >=0.8.0 <0.9.0; + +contract Validators { + address[] _validators = [ + 0x0000000000000000000000000000000000000010, + 0x0000000000000000000000000000000000000011, + 0x0000000000000000000000000000000000000012, + 0x0000000000000000000000000000000000000013, + 0x0000000000000000000000000000000000000014, + 0x0000000000000000000000000000000000000015, + 0x0000000000000000000000000000000000000016, + 0x0000000000000000000000000000000000000017, + 0x0000000000000000000000000000000000000018, + 0x0000000000000000000000000000000000000019, + 0x0000000000000000000000000000000000000020, + 0x0000000000000000000000000000000000000021, + 0x0000000000000000000000000000000000000022, + 0x0000000000000000000000000000000000000023, + 0x0000000000000000000000000000000000000024, + 0x0000000000000000000000000000000000000025, + 0x0000000000000000000000000000000000000026, + 0x0000000000000000000000000000000000000027, + 0x0000000000000000000000000000000000000028, + 0x0000000000000000000000000000000000000029, + 0x0000000000000000000000000000000000000030 + ]; + uint256[] _totalBalances = [1,4,6,2,8,9,10,3,16,20,100,12,22,30,50,60,5,18,16,22,21]; + constructor() {} + function getValidatorCandidates() public view returns (address[] memory _validatorList) { + _validatorList = _validators; + } + function totalBalances(address[] calldata _poolList) public view returns (uint256[] memory _balances) { + _balances = _totalBalances; + } +} +``` +*/ +var testSortCode = `6080604052604051806102a00160405280601073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001601173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001601273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001601373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001601473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001601573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001601673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001601773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001601873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001601973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001602073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001602173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001602273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001602373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001602473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001602573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001602673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001602773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001602873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001602973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001603073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250600090601561044d92919061054d565b50604051806102a00160405280600160ff168152602001600460ff168152602001600660ff168152602001600260ff168152602001600860ff168152602001600960ff168152602001600a60ff168152602001600360ff168152602001601060ff168152602001601460ff168152602001606460ff168152602001600c60ff168152602001601660ff168152602001601e60ff168152602001603260ff168152602001603c60ff168152602001600560ff168152602001601260ff168152602001601060ff168152602001601660ff168152602001601560ff16815250600190601561053a9291906105d7565b5034801561054757600080fd5b50610646565b8280548282559060005260206000209081019282156105c6579160200282015b828111156105c55782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509160200191906001019061056d565b5b5090506105d39190610629565b5090565b828054828255906000526020600020908101928215610618579160200282015b82811115610617578251829060ff169055916020019190600101906105f7565b5b5090506106259190610629565b5090565b5b8082111561064257600081600090555060010161062a565b5090565b610460806106556000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80634a5d76cd1461003b578063ba77b06c1461006b575b600080fd5b610055600480360381019061005091906101e1565b610089565b60405161006291906102f6565b60405180910390f35b6100736100e4565b6040516100809190610408565b60405180910390f35b606060018054806020026020016040519081016040528092919081815260200182805480156100d757602002820191906000526020600020905b8154815260200190600101908083116100c3575b5050505050905092915050565b6060600080548060200260200160405190810160405280929190818152602001828054801561016857602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161011e575b5050505050905090565b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b60008083601f8401126101a1576101a061017c565b5b8235905067ffffffffffffffff8111156101be576101bd610181565b5b6020830191508360208202830111156101da576101d9610186565b5b9250929050565b600080602083850312156101f8576101f7610172565b5b600083013567ffffffffffffffff81111561021657610215610177565b5b6102228582860161018b565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b61026d8161025a565b82525050565b600061027f8383610264565b60208301905092915050565b6000602082019050919050565b60006102a38261022e565b6102ad8185610239565b93506102b88361024a565b8060005b838110156102e95781516102d08882610273565b97506102db8361028b565b9250506001810190506102bc565b5085935050505092915050565b600060208201905081810360008301526103108184610298565b905092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061036f82610344565b9050919050565b61037f81610364565b82525050565b60006103918383610376565b60208301905092915050565b6000602082019050919050565b60006103b582610318565b6103bf8185610323565b93506103ca83610334565b8060005b838110156103fb5781516103e28882610385565b97506103ed8361039d565b9250506001810190506103ce565b5085935050505092915050565b6000602082019050818103600083015261042281846103aa565b90509291505056fea26469706673582212204aab6725297603e4a73daf57fffdd55330e60293dfde78dcbbddb9178144583064736f6c63430008110033` + +/** +wrapupCode is used to call sortValidators precompiled contract with the following code +``` +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.0 <0.9.0; + +contract Wrapup { + constructor() {} + + function sortValidators() public view returns (address[21] memory _validators) { + bytes memory payload = abi.encodeWithSignature("sortValidators(uint256)", 21); + uint payloadLength = payload.length; + address _smc = address(0x66); + assembly { + let payloadStart := add(payload, 32) + if iszero(staticcall(0, _smc, payloadStart, payloadLength, _validators, 0x2e0)) { + revert(0, 0) + } + returndatacopy(_validators, 64, 672) + return(_validators, 672) + } + } +} +``` +*/ +var ( + wrapupCode = `608060405234801561001057600080fd5b506102d8806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c806327167aec14610030575b600080fd5b61003861004e565b6040516100459190610219565b60405180910390f35b610056610119565b6000601560405160240161006a9190610287565b6040516020818303038152906040527f2e73ae11000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600081519050600060669050602083016102e0858483856000fa61010c57600080fd5b6102a06040863e6102a085f35b604051806102a00160405280601590602082028036833780820191505090505090565b600060159050919050565b600081905092915050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101878261015c565b9050919050565b6101978161017c565b82525050565b60006101a9838361018e565b60208301905092915050565b6000602082019050919050565b6101cb8161013c565b6101d58184610147565b92506101e082610152565b8060005b838110156102115781516101f8878261019d565b9650610203836101b5565b9250506001810190506101e4565b505050505050565b60006102a08201905061022f60008301846101c2565b92915050565b6000819050919050565b600060ff82169050919050565b6000819050919050565b600061027161026c61026784610235565b61024c565b61023f565b9050919050565b61028181610256565b82525050565b600060208201905061029c6000830184610278565b9291505056fea2646970667358221220d9e99c6aa93156ae399b93dff44f456409a5715d61d7f761ea1ed96a42bba43864736f6c63430008110033` + wrapupAbi = `[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"sortValidators","outputs":[{"internalType":"address[21]","name":"_validators","type":"address[21]"}],"stateMutability":"view","type":"function"}]` +) + +var ( + caller = common.BytesToAddress([]byte("sender")) + expectedValidators = []common.Address{ + common.HexToAddress("0x0000000000000000000000000000000000000020"), + common.HexToAddress("0x0000000000000000000000000000000000000025"), + common.HexToAddress("0x0000000000000000000000000000000000000024"), + common.HexToAddress("0x0000000000000000000000000000000000000023"), + common.HexToAddress("0x0000000000000000000000000000000000000029"), + common.HexToAddress("0x0000000000000000000000000000000000000022"), + common.HexToAddress("0x0000000000000000000000000000000000000030"), + common.HexToAddress("0x0000000000000000000000000000000000000019"), + common.HexToAddress("0x0000000000000000000000000000000000000027"), + common.HexToAddress("0x0000000000000000000000000000000000000028"), + common.HexToAddress("0x0000000000000000000000000000000000000018"), + common.HexToAddress("0x0000000000000000000000000000000000000021"), + common.HexToAddress("0x0000000000000000000000000000000000000016"), + common.HexToAddress("0x0000000000000000000000000000000000000015"), + common.HexToAddress("0x0000000000000000000000000000000000000014"), + common.HexToAddress("0x0000000000000000000000000000000000000012"), + common.HexToAddress("0x0000000000000000000000000000000000000026"), + common.HexToAddress("0x0000000000000000000000000000000000000011"), + common.HexToAddress("0x0000000000000000000000000000000000000017"), + common.HexToAddress("0x0000000000000000000000000000000000000013"), + common.HexToAddress("0x0000000000000000000000000000000000000010"), + } +) + +func TestSort(t *testing.T) { + addrs := []common.Address{ + common.BytesToAddress([]byte{102}), + common.BytesToAddress([]byte{103}), + common.BytesToAddress([]byte{104}), + common.BytesToAddress([]byte{105}), + common.BytesToAddress([]byte{106}), + } + + totalBalances := []*big.Int{ + big.NewInt(10), + big.NewInt(2), + big.NewInt(11), + big.NewInt(15), + big.NewInt(1), + } + + expectedAddrs := []common.Address{ + common.BytesToAddress([]byte{105}), + common.BytesToAddress([]byte{104}), + common.BytesToAddress([]byte{102}), + common.BytesToAddress([]byte{103}), + common.BytesToAddress([]byte{106}), + } + + expectedBalances := []*big.Int{ + big.NewInt(15), + big.NewInt(11), + big.NewInt(10), + big.NewInt(2), + big.NewInt(1), + } + + sortValidators(addrs, totalBalances) + for i, val := range addrs { + println(fmt.Sprintf("%s:%s", val.Hex(), totalBalances[i].String())) + if expectedBalances[i].Cmp(totalBalances[i]) != 0 { + t.Fatal(fmt.Sprintf("mismatched balance at %d, expected:%s got:%s", i, expectedBalances[i].String(), totalBalances[i].String())) + } + if expectedAddrs[i].Hex() != val.Hex() { + t.Fatal(fmt.Sprintf("mismatched addr at %d, expected:%s got:%s", i, expectedValidators[i].Hex(), val.Hex())) + } + } +} + +func TestConsortiumValidatorSorting_Run(t *testing.T) { + var ( + statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) + limit = 21 + ) + + smcAbi, err := abi.JSON(strings.NewReader(consortiumSortValidatorAbi)) + if err != nil { + t.Fatal(err) + } + input, err := smcAbi.Pack(sortValidatorsMethod, big.NewInt(int64(limit))) + if err != nil { + t.Fatal(err) + } + + evm, err := newEVM(caller, statedb) + if err != nil { + t.Fatal(err) + } + c := &consortiumValidatorSorting{caller: AccountRef(caller), evm: evm} + output, err := c.Run(input) + if err != nil { + t.Fatal(err) + } + println(common.Bytes2Hex(output)) + + res, err := smcAbi.Methods[sortValidatorsMethod].Outputs.Unpack(output) + if err != nil { + t.Fatal(err) + } + sortedValidators := *abi.ConvertType(res[0], new([]common.Address)).(*[]common.Address) + if len(expectedValidators) != len(sortedValidators) { + t.Fatal(fmt.Sprintf("expected len %d, got %v", limit, len(sortedValidators))) + } + for i, addr := range sortedValidators { + println(addr.Hex()) + if expectedValidators[i].Hex() != addr.Hex() { + t.Fatal(fmt.Sprintf("mismatched addr at %d, expected:%s got:%s", i, expectedValidators[i].Hex(), addr.Hex())) + } + } +} + +// TestConsortiumValidatorSorting_Run2 simulates a call from a user who trigger system contract to call `sort` precompiled contract +func TestConsortiumValidatorSorting_Run2(t *testing.T) { + var ( + statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) + ) + smcAbi, err := abi.JSON(strings.NewReader(wrapupAbi)) + if err != nil { + t.Fatal(err) + } + input, err := smcAbi.Pack(sortValidatorsMethod) + if err != nil { + t.Fatal(err) + } + evm, err := newEVM(caller, statedb) + if err != nil { + t.Fatal(err) + } + _, contract, _, err := evm.Create(AccountRef(caller), common.FromHex(wrapupCode), math.MaxUint64/2, big0) + if err != nil { + t.Fatal(err) + } + + // set this contract into consortiumV2Contracts to make it become a system contract + evm.chainConfig.ConsortiumV2Contracts.SlashIndicator = contract + + ret, _, err := evm.StaticCall(AccountRef(caller), contract, input, 1000000) + if err != nil { + t.Fatal(err) + } + + res, err := smcAbi.Methods[sortValidatorsMethod].Outputs.Unpack(ret) + if err != nil { + t.Fatal(err) + } + + sortedValidators := *abi.ConvertType(res[0], new([21]common.Address)).(*[21]common.Address) + if len(expectedValidators) != len(sortedValidators) { + t.Fatal(fmt.Sprintf("expected len 21, got %v", len(sortedValidators))) + } + for i, addr := range sortedValidators { + println(addr.Hex()) + if expectedValidators[i].Hex() != addr.Hex() { + t.Fatal(fmt.Sprintf("mismatched addr at %d, expected:%s got:%s", i, expectedValidators[i].Hex(), addr.Hex())) + } + } +} + +func newEVM(caller common.Address, statedb StateDB) (*EVM, error) { + evm := &EVM{ + Context: BlockContext{ + CanTransfer: func(state StateDB, addr common.Address, value *big.Int) bool { return true }, + Transfer: func(StateDB, common.Address, common.Address, *big.Int) {}, + }, + chainConfig: params.TestChainConfig, + StateDB: statedb, + chainRules: params.Rules{IsIstanbul: true}, + } + evm.interpreter = NewEVMInterpreter(evm, Config{NoBaseFee: true}) + _, contract, _, err := evm.Create(AccountRef(caller), common.FromHex(testSortCode), math.MaxUint64/2, big0) + if err != nil { + return nil, err + } + evm.chainConfig.ConsortiumV2Contracts = ¶ms.ConsortiumV2Contracts{ + StakingContract: contract, + RoninValidatorSet: contract, + SlashIndicator: caller, + } + return evm, nil +} diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 5e4b44e450..696230769f 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -20,12 +20,6 @@ import ( "crypto/sha256" "encoding/binary" "errors" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/log" - "math/big" - "os" - "strings" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" @@ -33,6 +27,7 @@ import ( "github.com/ethereum/go-ethereum/crypto/bls12381" "github.com/ethereum/go-ethereum/crypto/bn256" "github.com/ethereum/go-ethereum/params" + "math/big" //lint:ignore SA1019 Needed for precompile "golang.org/x/crypto/ripemd160" @@ -110,16 +105,11 @@ var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{18}): &bls12381MapG2{}, } -var PrecompiledContractsConsortium = map[common.Address]PrecompiledContract{ - common.BytesToAddress([]byte{101}): &consortiumLog{}, -} - var ( - PrecompiledAddressesBerlin []common.Address - PrecompiledAddressesIstanbul []common.Address - PrecompiledAddressesByzantium []common.Address - PrecompiledAddressesHomestead []common.Address - PrecompiledAddressesConsortium []common.Address + PrecompiledAddressesBerlin []common.Address + PrecompiledAddressesIstanbul []common.Address + PrecompiledAddressesByzantium []common.Address + PrecompiledAddressesHomestead []common.Address ) func init() { @@ -135,9 +125,6 @@ func init() { for k := range PrecompiledContractsBerlin { PrecompiledAddressesBerlin = append(PrecompiledAddressesBerlin, k) } - for k := range PrecompiledContractsConsortium { - PrecompiledAddressesConsortium = append(PrecompiledAddressesConsortium, k) - } } // ActivePrecompiles returns the precompiles enabled with the current configuration. @@ -1069,42 +1056,3 @@ func (c *bls12381MapG2) Run(input []byte) ([]byte, error) { // Encode the G2 point to 256 bytes return g.EncodePoint(r), nil } - -var consortiumLogAbi = `[{"inputs":[{"internalType":"string","name":"message","type":"string"}],"name":"log","outputs":[],"stateMutability":"nonpayable","type":"function"}]` - -type consortiumLog struct{} - -func (c *consortiumLog) RequiredGas(input []byte) uint64 { - return 0 -} - -func (c *consortiumLog) Run(input []byte) ([]byte, error) { - if os.Getenv("DEBUG") != "true" { - return input, nil - } - var ( - pAbi abi.ABI - err error - method *abi.Method - args []interface{} - ) - if pAbi, err = abi.JSON(strings.NewReader(consortiumLogAbi)); err != nil { - return nil, err - } - if method, err = pAbi.MethodById(input); err != nil { - return nil, err - } - switch method.Name { - case "log": - if args, err = method.Inputs.Unpack(input[4:]); err != nil { - return nil, err - } - if len(args) == 0 { - return input, nil - } - if _, ok := args[0].(string); ok { - log.Info("[consortiumLog] log message from smart contract", "message", args[0].(string)) - } - } - return input, nil -} diff --git a/core/vm/evm.go b/core/vm/evm.go index a9ca395747..8c788d8650 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -56,7 +56,7 @@ type ( BlockHash common.Hash ) -func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { +func (evm *EVM) precompile(caller ContractRef, addr common.Address) (PrecompiledContract, bool) { if c := evm.ChainConfig().BlacklistContractAddress; evm.chainRules.IsOdysseusFork && evm.StateDB.Blacklisted(c, &addr) { return &blacklistedAddress{}, true } @@ -80,7 +80,7 @@ func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { } // add consortium precompiled contracts to list - for address, contract := range PrecompiledContractsConsortium { + for address, contract := range PrecompiledContractsConsortium(caller, evm) { precompiles[address] = contract } @@ -217,7 +217,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas return nil, gas, ErrInsufficientBalance } snapshot := evm.StateDB.Snapshot() - p, isPrecompile := evm.precompile(addr) + p, isPrecompile := evm.precompile(caller, addr) if !evm.StateDB.Exist(addr) { if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 { @@ -319,7 +319,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, } // It is allowed to call precompiles, even via delegatecall - if p, isPrecompile := evm.precompile(addr); isPrecompile { + if p, isPrecompile := evm.precompile(caller, addr); isPrecompile { ret, gas, err = RunPrecompiledContract(p, input, gas) } else { addrCopy := addr @@ -363,7 +363,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by } // It is allowed to call precompiles, even via delegatecall - if p, isPrecompile := evm.precompile(addr); isPrecompile { + if p, isPrecompile := evm.precompile(caller, addr); isPrecompile { ret, gas, err = RunPrecompiledContract(p, input, gas) } else { addrCopy := addr @@ -415,7 +415,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte }(gas) } - if p, isPrecompile := evm.precompile(addr); isPrecompile { + if p, isPrecompile := evm.precompile(caller, addr); isPrecompile { ret, gas, err = RunPrecompiledContract(p, input, gas) } else { // At this point, we use a copy of address. If we don't, the go compiler will diff --git a/params/config.go b/params/config.go index dcfd1d4321..88366690cf 100644 --- a/params/config.go +++ b/params/config.go @@ -420,6 +420,7 @@ func (c *ConsortiumConfig) String() string { } type ConsortiumV2Contracts struct { + StakingContract common.Address `json:"stakingContract"` RoninValidatorSet common.Address `json:"roninValidatorSet"` SlashIndicator common.Address `json:"slashIndicator"` } From 89dde97b8001a551a5070affc438485b15d6d9e8 Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Mon, 3 Oct 2022 13:37:38 +0700 Subject: [PATCH 42/52] [RON-264] docs(contract): add code comments (#139) * docs(contract): add comments * docs(contract): update comment for GetValidators --- consensus/consortium/common/contract.go | 75 ++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 9 deletions(-) diff --git a/consensus/consortium/common/contract.go b/consensus/consortium/common/contract.go index d54700b4f0..6fdbe2451d 100644 --- a/consensus/consortium/common/contract.go +++ b/consensus/consortium/common/contract.go @@ -29,9 +29,11 @@ import ( var errMethodUnimplemented = errors.New("method is unimplemented") +// getTransactionOpts is a helper function that creates TransactOpts with GasPrice equals 0 func getTransactionOpts(from common.Address, nonce uint64, chainId *big.Int, signTxFn SignerTxFn) *bind.TransactOpts { return &bind.TransactOpts{ - From: from, + From: from, + // FIXME(linh): Decrease gasLimit later, math.MaxUint64 / 2 is too large GasLimit: uint64(math.MaxUint64 / 2), GasPrice: big.NewInt(0), // Set dummy value always equal 0 since it will be overridden when creating a new message @@ -39,6 +41,7 @@ func getTransactionOpts(from common.Address, nonce uint64, chainId *big.Int, sig Nonce: new(big.Int).SetUint64(nonce), NoSend: true, Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) { + // signTxFn is nil when mining is not enabled, then we just return the transaction directly if signTxFn == nil { return tx, nil } @@ -48,6 +51,7 @@ func getTransactionOpts(from common.Address, nonce uint64, chainId *big.Int, sig } } +// ContractIntegrator is a contract facing to interact with smart contract that supports DPoS type ContractIntegrator struct { chainId *big.Int signer types.Signer @@ -57,11 +61,15 @@ type ContractIntegrator struct { coinbase common.Address } +// NewContractIntegrator creates new ContractIntegrator with custom backend and signTxFn func NewContractIntegrator(config *chainParams.ChainConfig, backend bind.ContractBackend, signTxFn SignerTxFn, coinbase common.Address) (*ContractIntegrator, error) { + // Create Ronin Validator Set smart contract roninValidatorSetSC, err := roninValidatorSet.NewRoninValidatorSet(config.ConsortiumV2Contracts.RoninValidatorSet, backend) if err != nil { return nil, err } + + // Create Slash Indicator smart contract slashIndicatorSC, err := slashIndicator.NewSlashIndicator(config.ConsortiumV2Contracts.SlashIndicator, backend) if err != nil { return nil, err @@ -77,6 +85,7 @@ func NewContractIntegrator(config *chainParams.ChainConfig, backend bind.Contrac }, nil } +// GetValidators retrieves top validators addresses func (c *ContractIntegrator) GetValidators(blockNumber *big.Int) ([]common.Address, error) { callOpts := bind.CallOpts{ BlockNumber: blockNumber, @@ -88,12 +97,14 @@ func (c *ContractIntegrator) GetValidators(blockNumber *big.Int) ([]common.Addre return addresses, nil } +// WrapUpEpoch distributes rewards to validators and updates validators set func (c *ContractIntegrator) WrapUpEpoch(opts *ApplyTransactOpts) error { nonce := opts.State.GetNonce(c.coinbase) tx, err := c.roninValidatorSetSC.WrapUpEpoch(getTransactionOpts(c.coinbase, nonce, c.chainId, c.signTxFn)) if err != nil { return err } + msg := types.NewMessage( opts.Header.Coinbase, tx.To(), @@ -107,14 +118,17 @@ func (c *ContractIntegrator) WrapUpEpoch(opts *ApplyTransactOpts) error { tx.AccessList(), false, ) - err = ApplyTransaction(msg, opts) - if err != nil { + + if err = ApplyTransaction(msg, opts); err != nil { return err } + log.Info("Wrapped up epoch", "block hash", opts.Header.Hash(), "tx hash", tx.Hash().Hex()) return err } +// SubmitBlockReward submits a transaction to the ValidatorSetSC that gets balance from sender +// plus bonus from vesting contract in order to updates mining reward and delegating reward func (c *ContractIntegrator) SubmitBlockReward(opts *ApplyTransactOpts) error { coinbase := opts.Header.Coinbase balance := opts.State.GetBalance(consensus.SystemAddress) @@ -125,11 +139,11 @@ func (c *ContractIntegrator) SubmitBlockReward(opts *ApplyTransactOpts) error { opts.State.AddBalance(coinbase, balance) nonce := opts.State.GetNonce(c.coinbase) - log.Info("Submitted block reward", "block hash", opts.Header.Hash(), "amount", balance.String(), "coinbase", c.coinbase.Hex(), "nonce", nonce) tx, err := c.roninValidatorSetSC.SubmitBlockReward(getTransactionOpts(c.coinbase, nonce, c.chainId, c.signTxFn)) if err != nil { return err } + log.Info("Submitted block reward", "block hash", opts.Header.Hash(), "tx hash", tx.Hash().Hex(), "amount", balance.Uint64()) msg := types.NewMessage( opts.Header.Coinbase, @@ -146,14 +160,15 @@ func (c *ContractIntegrator) SubmitBlockReward(opts *ApplyTransactOpts) error { false, ) - err = ApplyTransaction(msg, opts) - if err != nil { + if err = ApplyTransaction(msg, opts); err != nil { return err } return nil } +// Slash submits a transaction to the SlashIndicatorSC that checks the unavailability of the coinbase +// and calls the slash method corresponding func (c *ContractIntegrator) Slash(opts *ApplyTransactOpts, spoiledValidator common.Address) error { nonce := opts.State.GetNonce(c.coinbase) tx, err := c.slashIndicatorSC.Slash(getTransactionOpts(c.coinbase, nonce, c.chainId, c.signTxFn), spoiledValidator) @@ -174,14 +189,15 @@ func (c *ContractIntegrator) Slash(opts *ApplyTransactOpts, spoiledValidator com tx.AccessList(), false, ) - err = ApplyTransaction(msg, opts) - if err != nil { + + if err = ApplyTransaction(msg, opts); err != nil { return err } return nil } +// ApplyMessageOpts is the collection of options to fine tune a contract call request. type ApplyMessageOpts struct { State *state.StateDB Header *types.Header @@ -189,6 +205,8 @@ type ApplyMessageOpts struct { ChainContext core.ChainContext } +// ApplyTransactOpts is the collection of authorization data required to create a +// valid transaction. type ApplyTransactOpts struct { *ApplyMessageOpts Txs *[]*types.Transaction @@ -201,6 +219,9 @@ type ApplyTransactOpts struct { EthAPI *ethapi.PublicBlockChainAPI } +// ApplyTransaction attempts to apply a transaction to the given state database +// and uses the input parameters for its environment. It returns nil if applied success +// and an error if the transaction failed, indicating the block was invalid. func ApplyTransaction(msg types.Message, opts *ApplyTransactOpts) (err error) { signer := opts.Signer signTxFn := opts.SignTxFn @@ -214,6 +235,7 @@ func ApplyTransaction(msg types.Message, opts *ApplyTransactOpts) (err error) { usedGas := opts.UsedGas nonce := msg.Nonce() + // TODO(linh): This function is deprecated. Shall we replace it with NewTx? expectedTx := types.NewTransaction(nonce, *msg.To(), msg.Value(), msg.Gas(), msg.GasPrice(), msg.Data()) expectedHash := signer.Hash(expectedTx) @@ -226,6 +248,8 @@ func ApplyTransaction(msg types.Message, opts *ApplyTransactOpts) (err error) { if receivedTxs == nil || len(*receivedTxs) == 0 || (*receivedTxs)[0] == nil { return errors.New("supposed to get a actual transaction, but get none") } + // receivedTxs (a.k.a systemTxs) is collected by the method Process of state_processor + // The system transaction is the transaction that have the receiver is ConsortiumV2Contracts actualTx := (*receivedTxs)[0] if !bytes.Equal(signer.Hash(actualTx).Bytes(), expectedHash.Bytes()) { return fmt.Errorf("expected tx hash %v, get %v, nonce %d, to %s, value %s, gas %d, gasPrice %s, data %s", expectedHash.String(), actualTx.Hash().String(), @@ -243,10 +267,11 @@ func ApplyTransaction(msg types.Message, opts *ApplyTransactOpts) (err error) { } opts.State.Prepare(expectedTx.Hash(), len(*txs)) gasUsed, err := applyMessage(msg, opts.ApplyMessageOpts) - log.Debug("ApplyTransaction", "gasUsed", gasUsed) if err != nil { return err } + log.Debug("Applied transaction", "gasUsed", gasUsed) + *txs = append(*txs, expectedTx) var root []byte if chainConfig.IsByzantium(opts.Header.Number) { @@ -255,6 +280,8 @@ func ApplyTransaction(msg types.Message, opts *ApplyTransactOpts) (err error) { root = opts.State.IntermediateRoot(chainConfig.IsEIP158(opts.Header.Number)).Bytes() } *usedGas += gasUsed + + // TODO(linh): This function is deprecated. Shall we replace it with Receipt struct? receipt := types.NewReceipt(root, false, *usedGas) receipt.TxHash = expectedTx.Hash() receipt.GasUsed = gasUsed @@ -270,6 +297,7 @@ func ApplyTransaction(msg types.Message, opts *ApplyTransactOpts) (err error) { return nil } +// applyMessage creates new evm and applies a transaction to the current state func applyMessage( msg types.Message, opts *ApplyMessageOpts, @@ -293,16 +321,20 @@ func applyMessage( return msg.Gas() - returnGas, err } +// ConsortiumBackend is a custom backend that supports call smart contract by using *ethapi.PublicBlockChainAPI type ConsortiumBackend struct { *ethapi.PublicBlockChainAPI } +// NewConsortiumBackend creates new ConsortiumBackend from *ethapi.PublicBlockChainAPI func NewConsortiumBackend(ee *ethapi.PublicBlockChainAPI) *ConsortiumBackend { return &ConsortiumBackend{ ee, } } +// CodeAt returns the code of the given account. This is needed to differentiate +// between contract internal errors and the local chain being out of sync. func (b *ConsortiumBackend) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) { blkNumber := rpc.LatestBlockNumber if blockNumber != nil { @@ -317,6 +349,8 @@ func (b *ConsortiumBackend) CodeAt(ctx context.Context, contract common.Address, return result.MarshalText() } +// CallContract executes an Ethereum contract call with the specified data as the +// input. func (b *ConsortiumBackend) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { blkNumber := rpc.LatestBlockNumber if blockNumber != nil { @@ -338,39 +372,62 @@ func (b *ConsortiumBackend) CallContract(ctx context.Context, call ethereum.Call return result, nil } +// HeaderByNumber returns a block header from the current canonical chain. If +// number is nil, the latest known header is returned. func (b *ConsortiumBackend) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { return b.GetHeader(ctx, rpc.BlockNumber(number.Int64())) } +// PendingCodeAt returns the code of the given account in the pending state. +// NOTE(linh): This method is never called, implement for interface purposes func (b *ConsortiumBackend) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) { return nil, errMethodUnimplemented } +// PendingNonceAt retrieves the current pending nonce associated with an account. +// NOTE(linh): This method is never called, implement for interface purposes func (b *ConsortiumBackend) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { return 0, errMethodUnimplemented } +// SuggestGasPrice retrieves the currently suggested gas price to allow a timely +// execution of a transaction. +// NOTE(linh): This method is never called, implement for interface purposes func (b *ConsortiumBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error) { return big.NewInt(0), nil } +// SuggestGasTipCap retrieves the currently suggested 1559 priority fee to allow +// a timely execution of a transaction. +// NOTE(linh): This method is never called, implement for interface purposes func (b *ConsortiumBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { return big.NewInt(0), nil } +// EstimateGas tries to estimate the gas needed to execute a specific +// transaction based on the current pending state of the backend blockchain. +// NOTE(linh): We allow math.MaxUint64 / 2 because it is only called by the validator func (b *ConsortiumBackend) EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error) { return math.MaxUint64 / 2, nil } +// SendTransaction injects the transaction into the pending pool for execution. +// NOTE(linh): This method is never called, implement for interface purposes. We call ApplyTransaction directly func (b *ConsortiumBackend) SendTransaction(ctx context.Context, tx *types.Transaction) error { // No need to send transaction return errMethodUnimplemented } +// FilterLogs executes a log filter operation, blocking during execution and +// returning all the results in one batch. +// NOTE(linh): This method is never called, implement for interface purposes func (b *ConsortiumBackend) FilterLogs(ctx context.Context, query ethereum.FilterQuery) ([]types.Log, error) { return nil, errMethodUnimplemented } +// SubscribeFilterLogs creates a background log filtering operation, returning +// a subscription immediately, which can be used to stream the found events. +// NOTE(linh): This method is never called, implement for interface purposes func (b *ConsortiumBackend) SubscribeFilterLogs(ctx context.Context, query ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) { return nil, errMethodUnimplemented } From b4be6f2716a663d18b2fe1e08da29a0cde7f89eb Mon Sep 17 00:00:00 2001 From: minh-bq <97180373+minh-bq@users.noreply.github.com> Date: Mon, 3 Oct 2022 14:39:19 +0700 Subject: [PATCH 43/52] fix: return error when failed to slash, wrap up (#133) --- consensus/consortium/v2/consortium.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index b8ebdebe21..5a35f0f8f5 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -539,6 +539,7 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H if err != nil { // it is possible that slash validator failed because of the slash channel is disabled. log.Error("slash validator failed", "block hash", header.Hash(), "address", spoiledVal) + return err } } } @@ -546,6 +547,7 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H if header.Number.Uint64()%c.config.Epoch == c.config.Epoch-1 { if err := c.contract.WrapUpEpoch(transactOpts); err != nil { log.Error("Failed to update validators", "err", err) + return err } } @@ -607,6 +609,7 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head if err != nil { // it is possible that slash validator failed because of the slash channel is disabled. log.Error("Slash validator failed", "block hash", header.Hash(), "address", spoiledVal, "error", err) + return nil, nil, err } } } @@ -614,6 +617,7 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head if header.Number.Uint64()%c.config.Epoch == c.config.Epoch-1 { if err := c.contract.WrapUpEpoch(transactOpts); err != nil { log.Error("Wrap up epoch failed", "block hash", header.Hash(), "error", err) + return nil, nil, err } } From 73c5780e508f1b6d2d908bb896f4e11f6307a295 Mon Sep 17 00:00:00 2001 From: Kien Dang Date: Fri, 7 Oct 2022 14:36:29 +0700 Subject: [PATCH 44/52] feat: Implement verifyHeaders precompiled contract which detects double signing issue (#143) * feat: Implement verifyHeaders precompiled contract which detects double signing issue * chore: Remove unnecessary log init * chore: simplify unit test, add chainId and change Number to big.Int * chore: clean up code * nit: comment to hacky (`unpack`) function * chore: Add condition signer must equal to coinbase to prevent user uses fake signature --- core/vm/consortium_precompiled_contracts.go | 192 ++++++++++++++++ .../consortium_precompiled_contracts_test.go | 217 ++++++++++++++++++ 2 files changed, 409 insertions(+) diff --git a/core/vm/consortium_precompiled_contracts.go b/core/vm/consortium_precompiled_contracts.go index 2325f4b500..55f0fa13b1 100644 --- a/core/vm/consortium_precompiled_contracts.go +++ b/core/vm/consortium_precompiled_contracts.go @@ -6,16 +6,23 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rlp" + "golang.org/x/crypto/sha3" + "io" "math/big" "math/rand" "os" "strings" + "time" ) var ( consortiumLogAbi = `[{"inputs":[{"internalType":"string","name":"message","type":"string"}],"name":"log","outputs":[],"stateMutability":"nonpayable","type":"function"}]` consortiumSortValidatorAbi = `[{"inputs":[],"name":"getValidatorCandidates","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"sortValidators","outputs":[{"internalType":"address[]","name":"validators","type":"address[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_poolList","type":"address[]"}],"name":"totalBalances","outputs":[{"internalType":"uint256[]","name":"_balances","type":"uint256[]"}],"stateMutability":"view","type":"function"}]` + consortiumVerifyHeadersAbi = `[{"outputs":[],"name":"getHeader","inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"bytes32","name":"parentHash","type":"bytes32"},{"internalType":"bytes32","name":"ommersHash","type":"bytes32"},{"internalType":"address","name":"coinbase","type":"address"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"internalType":"bytes32","name":"transactionsRoot","type":"bytes32"},{"internalType":"bytes32","name":"receiptsRoot","type":"bytes32"},{"internalType":"uint8[256]","name":"logsBloom","type":"uint8[256]"},{"internalType":"uint256","name":"difficulty","type":"uint256"},{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint64","name":"gasLimit","type":"uint64"},{"internalType":"uint64","name":"gasUsed","type":"uint64"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"bytes","name":"extraData","type":"bytes"},{"internalType":"bytes32","name":"mixHash","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"header1","type":"bytes"},{"internalType":"bytes","name":"header2","type":"bytes"}],"name":"validatingDoubleSignProof","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]` ) const ( @@ -23,12 +30,16 @@ const ( logMethod = "log" getValidatorsMethod = "getValidatorCandidates" totalBalancesMethod = "totalBalances" + verifyHeaders = "validatingDoubleSignProof" + getHeader = "getHeader" + extraVanity = 32 ) func PrecompiledContractsConsortium(caller ContractRef, evm *EVM) map[common.Address]PrecompiledContract { return map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{101}): &consortiumLog{}, common.BytesToAddress([]byte{102}): &consortiumValidatorSorting{caller: caller, evm: evm}, + common.BytesToAddress([]byte{103}): &consortiumVerifyHeaders{caller: caller, evm: evm}, } } @@ -194,3 +205,184 @@ func loadMethodAndArgs(smcAbi string, input []byte) (abi.ABI, *abi.Method, []int } return pAbi, method, args, nil } + +type BlockHeader struct { + ChainId *big.Int `abi:"chainId"` + ParentHash [32]uint8 `abi:"parentHash"` + OmmersHash [32]uint8 `abi:"ommersHash"` + Benificiary common.Address `abi:"coinbase"` + StateRoot [32]uint8 `abi:"stateRoot"` + TransactionsRoot [32]uint8 `abi:"transactionsRoot"` + ReceiptsRoot [32]uint8 `abi:"receiptsRoot"` + LogsBloom [256]uint8 `abi:"logsBloom"` + Difficulty *big.Int `abi:"difficulty"` + Number *big.Int `abi:"number"` + GasLimit uint64 `abi:"gasLimit"` + GasUsed uint64 `abi:"gasUsed"` + Timestamp uint64 `abi:"timestamp"` + ExtraData []byte `abi:"extraData"` + MixHash [32]uint8 `abi:"mixHash"` + Nonce uint64 `abi:"nonce"` +} + +func fromHeader(header *types.Header, chainId *big.Int) *BlockHeader { + blockHeader := &BlockHeader{ + ChainId: chainId, + Difficulty: header.Difficulty, + Number: header.Number, + GasLimit: header.GasLimit, + GasUsed: header.GasUsed, + Timestamp: header.Time, + Nonce: header.Nonce.Uint64(), + ExtraData: header.Extra, + LogsBloom: header.Bloom, + Benificiary: header.Coinbase, + } + copy(blockHeader.ParentHash[:], header.ParentHash.Bytes()) + copy(blockHeader.StateRoot[:], header.Root.Bytes()) + copy(blockHeader.TransactionsRoot[:], header.TxHash.Bytes()) + copy(blockHeader.ReceiptsRoot[:], header.ReceiptHash.Bytes()) + copy(blockHeader.MixHash[:], header.MixDigest.Bytes()) + return blockHeader +} + +func (b *BlockHeader) toHeader() *types.Header { + return &types.Header{ + ParentHash: common.BytesToHash(b.ParentHash[:]), + Root: common.BytesToHash(b.StateRoot[:]), + TxHash: common.BytesToHash(b.TransactionsRoot[:]), + ReceiptHash: common.BytesToHash(b.ReceiptsRoot[:]), + Bloom: types.BytesToBloom(b.LogsBloom[:]), + Difficulty: b.Difficulty, + Number: b.Number, + GasLimit: b.GasLimit, + GasUsed: b.GasUsed, + Time: b.Timestamp, + Extra: b.ExtraData, + MixDigest: common.BytesToHash(b.MixHash[:]), + Nonce: types.EncodeNonce(b.Nonce), + Coinbase: b.Benificiary, + } +} + +func (b *BlockHeader) Bytes() ([]byte, error) { + pAbi, _ := abi.JSON(strings.NewReader(consortiumVerifyHeadersAbi)) + bloom := types.BytesToBloom(b.LogsBloom[:]) + var uncles [32]uint8 + return pAbi.Methods[getHeader].Inputs.Pack(b.ChainId, b.ParentHash, uncles, b.Benificiary, b.StateRoot, b.TransactionsRoot, b.ReceiptsRoot, bloom.Bytes(), b.Difficulty, b.Number, b.GasLimit, b.GasUsed, b.Timestamp, b.ExtraData, b.MixHash, b.Nonce) +} + +type consortiumVerifyHeaders struct { + caller ContractRef + evm *EVM +} + +func (c *consortiumVerifyHeaders) RequiredGas(input []byte) uint64 { + return 0 +} + +func (c *consortiumVerifyHeaders) Run(input []byte) ([]byte, error) { + if c.evm.ChainConfig().ConsortiumV2Contracts == nil { + return nil, errors.New("cannot find consortium v2 contracts") + } + if !c.evm.ChainConfig().ConsortiumV2Contracts.IsSystemContract(c.caller.Address()) { + return nil, errors.New("unauthorized sender") + } + // get method, args from abi + smcAbi, method, args, err := loadMethodAndArgs(consortiumVerifyHeadersAbi, input) + if err != nil { + return nil, err + } + if method.Name != verifyHeaders { + return nil, errors.New("invalid method") + } + if len(args) != 2 { + return nil, errors.New(fmt.Sprintf("invalid arguments, expected 2 got %d", len(args))) + } + // decode header1, header2 + var blockHeader1, blockHeader2 BlockHeader + if err := c.unpack(smcAbi, &blockHeader1, args[0].([]byte)); err != nil { + return nil, err + } + if err := c.unpack(smcAbi, &blockHeader2, args[1].([]byte)); err != nil { + return nil, err + } + output := c.verify(blockHeader1, blockHeader2) + return smcAbi.Methods[verifyHeaders].Outputs.Pack(output) +} + +func (c *consortiumVerifyHeaders) unpack(smcAbi abi.ABI, v interface{}, input []byte) error { + // use `getHeader` abi which contains params defined in `BlockHeader` to unmarshal `input` data into `BlockHeader` + args := smcAbi.Methods[getHeader].Inputs + output, err := args.Unpack(input) + if err != nil { + return err + } + return args.Copy(v, output) +} + +func (c *consortiumVerifyHeaders) getSigner(header BlockHeader) (common.Address, error) { + if header.Number == nil || header.Timestamp > uint64(time.Now().Unix()) || len(header.ExtraData) < crypto.SignatureLength { + return common.Address{}, errors.New("invalid header") + } + signature := header.ExtraData[len(header.ExtraData)-crypto.SignatureLength:] + + // Recover the public key and the Ethereum address + pubkey, err := crypto.Ecrecover(SealHash(header.toHeader(), header.ChainId).Bytes(), signature) + if err != nil { + return common.Address{}, err + } + var signer common.Address + copy(signer[:], crypto.Keccak256(pubkey[1:])[12:]) + + return signer, nil +} + +func (c *consortiumVerifyHeaders) verify(header1, header2 BlockHeader) bool { + if header1.toHeader().ParentHash.Hex() != header2.toHeader().ParentHash.Hex() { + return false + } + signer1, err := c.getSigner(header1) + if err != nil { + log.Trace("[consortiumVerifyHeaders][verify] error while getting signer from header1", "err", err) + return false + } + signer2, err := c.getSigner(header2) + if err != nil { + log.Trace("[consortiumVerifyHeaders][verify] error while getting signer from header2", "err", err) + return false + } + return signer1.Hex() == signer2.Hex() && signer2.Hex() == header2.Benificiary.Hex() +} + +// SealHash returns the hash of a block prior to it being sealed. +func SealHash(header *types.Header, chainId *big.Int) (hash common.Hash) { + hasher := sha3.NewLegacyKeccak256() + encodeSigHeader(hasher, header, chainId) + hasher.Sum(hash[:0]) + return hash +} + +func encodeSigHeader(w io.Writer, header *types.Header, chainId *big.Int) { + err := rlp.Encode(w, []interface{}{ + chainId, + header.ParentHash, + header.UncleHash, + header.Coinbase, + header.Root, + header.TxHash, + header.ReceiptHash, + header.Bloom, + header.Difficulty, + header.Number, + header.GasLimit, + header.GasUsed, + header.Time, + header.Extra[:len(header.Extra)-crypto.SignatureLength], // Yes, this will panic if extra is too short + header.MixDigest, + header.Nonce, + }) + if err != nil { + panic("can't encode: " + err.Error()) + } +} diff --git a/core/vm/consortium_precompiled_contracts_test.go b/core/vm/consortium_precompiled_contracts_test.go index c12a800b74..061e3abc46 100644 --- a/core/vm/consortium_precompiled_contracts_test.go +++ b/core/vm/consortium_precompiled_contracts_test.go @@ -1,12 +1,15 @@ package vm import ( + "bytes" "fmt" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" "math/big" "strings" @@ -114,6 +117,35 @@ var ( } ) +/** +verifyHeadersTestCode represents the following smart contract code +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.0 <0.9.0; + +contract VerifyHeaderTestContract { + + constructor() {} + + function verify(bytes memory header1, bytes memory header2) public view returns (bool) { + bytes memory payload = abi.encodeWithSignature("validatingDoubleSignProof(bytes,bytes)", header1, header2); + uint payloadLength = payload.length; + address _smc = address(0x67); + uint[1] memory _output; + assembly { + let payloadStart := add(payload, 32) + if iszero(staticcall(0, _smc, payloadStart, payloadLength, _output, 0x20)) { + revert(0, 0) + } + } + return (_output[0] != 0); + } +} +*/ +var ( + verifyHeadersTestCode = "608060405234801561001057600080fd5b50610299806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f7e83aee14610030575b600080fd5b61004361003e36600461018b565b610057565b604051901515815260200160405180910390f35b600080838360405160240161006d929190610235565b60408051601f198184030181529190526020810180516001600160e01b031663580a316360e01b179052805190915060676100a66100ca565b602084016020828583866000fa6100bc57600080fd5b505115159695505050505050565b60405180602001604052806001906020820280368337509192915050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261010f57600080fd5b813567ffffffffffffffff8082111561012a5761012a6100e8565b604051601f8301601f19908116603f01168101908282118183101715610152576101526100e8565b8160405283815286602085880101111561016b57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806040838503121561019e57600080fd5b823567ffffffffffffffff808211156101b657600080fd5b6101c2868387016100fe565b935060208501359150808211156101d857600080fd5b506101e5858286016100fe565b9150509250929050565b6000815180845260005b81811015610215576020818501810151868301820152016101f9565b506000602082860101526020601f19601f83011685010191505092915050565b60408152600061024860408301856101ef565b828103602084015261025a81856101ef565b9594505050505056fea2646970667358221220e689890bbe17c2e97389470ed4baa21af25fd9cd6348d7511924615440d967d364736f6c63430008110033" + verifyHeadersTestAbi = `[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"bytes","name":"header1","type":"bytes"},{"internalType":"bytes","name":"header2","type":"bytes"}],"name":"verify","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]` +) + func TestSort(t *testing.T) { addrs := []common.Address{ common.BytesToAddress([]byte{102}), @@ -248,6 +280,191 @@ func TestConsortiumValidatorSorting_Run2(t *testing.T) { } } +// TestConsortiumVerifyHeaders_verify tests verify function +func TestConsortiumVerifyHeaders_verify(t *testing.T) { + header1, header2, err := prepareHeader(big1) + if err != nil { + t.Fatal(err) + } + c := &consortiumVerifyHeaders{evm: &EVM{chainConfig: ¶ms.ChainConfig{ChainID: big1}}} + if !c.verify(*fromHeader(header1, big1), *fromHeader(header2, big1)) { + t.Fatal("expected true, got false") + } +} + +// TestConsortiumVerifyHeaders_Run init 2 headers, pack them and call `Run` function directly +func TestConsortiumVerifyHeaders_Run(t *testing.T) { + var ( + statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) + ) + smcAbi, err := abi.JSON(strings.NewReader(consortiumVerifyHeadersAbi)) + if err != nil { + t.Fatal(err) + } + evm, err := newEVM(caller, statedb) + if err != nil { + t.Fatal(err) + } + header1, header2, err := prepareHeader(evm.chainConfig.ChainID) + if err != nil { + t.Fatal(err) + } + encodedHeader1, err := fromHeader(header1, big1).Bytes() + if err != nil { + t.Fatal(err) + } + encodedHeader2, err := fromHeader(header2, big1).Bytes() + if err != nil { + t.Fatal(err) + } + input, err := smcAbi.Pack(verifyHeaders, encodedHeader1, encodedHeader2) + if err != nil { + t.Fatal(err) + } + c := &consortiumVerifyHeaders{evm: evm, caller: AccountRef(caller)} + result, err := c.Run(input) + if err != nil { + t.Fatal(err) + } + if len(result) != 32 { + t.Fatal(fmt.Sprintf("expected len 32 got %d", len(result))) + } + if result[len(result)-1] != 1 { + t.Fatal(fmt.Sprintf("expected 1 (true) got %d", result[len(result)-1])) + } +} + +// TestConsortiumVerifyHeaders_Run2 deploys smart contract and call precompiled contracts via this contract +func TestConsortiumVerifyHeaders_Run2(t *testing.T) { + var ( + statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) + ) + smcAbi, err := abi.JSON(strings.NewReader(verifyHeadersTestAbi)) + if err != nil { + t.Fatal(err) + } + header1, header2, err := prepareHeader(big1) + if err != nil { + t.Fatal(err) + } + encodedHeader1, err := fromHeader(header1, big1).Bytes() + if err != nil { + t.Fatal(err) + } + encodedHeader2, err := fromHeader(header2, big1).Bytes() + if err != nil { + t.Fatal(err) + } + input, err := smcAbi.Pack("verify", encodedHeader1, encodedHeader2) + if err != nil { + t.Fatal(err) + } + evm, err := newEVM(caller, statedb) + if err != nil { + t.Fatal(err) + } + _, contract, _, err := evm.Create(AccountRef(caller), common.FromHex(verifyHeadersTestCode), math.MaxUint64/2, big0) + if err != nil { + t.Fatal(err) + } + + // set this contract into consortiumV2Contracts to make it become a system contract + evm.chainConfig.ConsortiumV2Contracts.SlashIndicator = contract + + ret, _, err := evm.StaticCall(AccountRef(caller), contract, input, 1000000) + if err != nil { + t.Fatal(err) + } + + res, err := smcAbi.Methods["verify"].Outputs.Unpack(ret) + if err != nil { + t.Fatal(err) + } + result := *abi.ConvertType(res[0], new(bool)).(*bool) + if !result { + t.Fatal("expected true got false") + } +} + +func prepareHeader(chainId *big.Int) (*types.Header, *types.Header, error) { + privateKey, err := crypto.GenerateKey() + if err != nil { + return nil, nil, err + } + // init extraData with extraVanity + extraData := bytes.Repeat([]byte{0x00}, extraVanity) + + // append to extraData with validators set + extraData = append(extraData, common.BytesToAddress([]byte("validator1")).Bytes()...) + extraData = append(extraData, common.BytesToAddress([]byte("validator2")).Bytes()...) + + // add extra seal space + extraData = append(extraData, make([]byte, crypto.SignatureLength)...) + + // create header1 + header1 := &types.Header{ + ParentHash: common.BytesToHash([]byte("11")), + UncleHash: common.Hash{}, + Coinbase: crypto.PubkeyToAddress(privateKey.PublicKey), + Root: common.BytesToHash([]byte("123")), + TxHash: common.BytesToHash([]byte("abc")), + ReceiptHash: common.BytesToHash([]byte("def")), + Bloom: types.Bloom{}, + Difficulty: big.NewInt(1000), + Number: big.NewInt(1000), + GasLimit: 100000000, + GasUsed: 0, + Time: 1000, + Extra: make([]byte, len(extraData)), + MixDigest: common.Hash{}, + Nonce: types.EncodeNonce(1000), + } + + // create header2 + header2 := &types.Header{ + ParentHash: common.BytesToHash([]byte("11")), + UncleHash: common.Hash{}, + Coinbase: crypto.PubkeyToAddress(privateKey.PublicKey), + Root: common.BytesToHash([]byte("1232")), + TxHash: common.BytesToHash([]byte("abcd")), + ReceiptHash: common.BytesToHash([]byte("defd")), + Bloom: types.Bloom{}, + Difficulty: big.NewInt(1000), + Number: big.NewInt(1000), + GasLimit: 100000000, + GasUsed: 0, + Time: 1000, + Extra: make([]byte, len(extraData)), + MixDigest: common.Hash{}, + Nonce: types.EncodeNonce(1000), + } + + // copy extraData + copy(header1.Extra[:], extraData) + copy(header2.Extra[:], extraData) + + // signing and add to extraData + sig1, err := crypto.Sign(crypto.Keccak256(consortiumRlp(header1, chainId)), privateKey) + if err != nil { + return nil, nil, err + } + sig2, err := crypto.Sign(crypto.Keccak256(consortiumRlp(header2, chainId)), privateKey) + if err != nil { + return nil, nil, err + } + + copy(header1.Extra[len(header1.Extra)-crypto.SignatureLength:], sig1) + copy(header2.Extra[len(header2.Extra)-crypto.SignatureLength:], sig2) + + return header1, header2, nil +} + +func consortiumRlp(header *types.Header, chainId *big.Int) []byte { + b := new(bytes.Buffer) + encodeSigHeader(b, header, chainId) + return b.Bytes() +} + func newEVM(caller common.Address, statedb StateDB) (*EVM, error) { evm := &EVM{ Context: BlockContext{ From e474e1ef58b6c6c982fd09450a4efad2586f0169 Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Wed, 12 Oct 2022 11:36:44 +0700 Subject: [PATCH 45/52] [RON-274] docs(v2consortium): add code comments (#140) * docs(v2consortium): add code comments * docs(v2consortium): update Close comment * docs(v2consortium): fix typo error --- consensus/consortium/v2/consortium.go | 101 +++++++++++++++----- consensus/consortium/v2/consortiumv2fork.go | 1 + consensus/consortium/v2/snapshot.go | 34 ++++++- 3 files changed, 108 insertions(+), 28 deletions(-) diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index 5a35f0f8f5..e0a039d20b 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -41,7 +41,7 @@ const ( wiggleTime = 1000 * time.Millisecond // Random delay (per signer) to allow concurrent signers ) -// Consortium proof-of-authority protocol constants. +// Consortium delegated proof-of-stake protocol constants. var ( epochLength = uint64(30000) // Default number of blocks after which to checkpoint @@ -75,6 +75,8 @@ var ( errMismatchingEpochValidators = errors.New("mismatching validator list on epoch block") ) +// Consortium is the delegated proof-of-stake consensus engine proposed to support the +// Ronin to become more decentralized type Consortium struct { chainConfig *params.ChainConfig config *params.ConsortiumConfig // Consensus engine configuration parameters @@ -98,6 +100,7 @@ type Consortium struct { v1 consortiumCommon.ConsortiumAdapter } +// New creates a Consortium delegated proof-of-stake consensus engine func New( chainConfig *params.ChainConfig, db ethdb.Database, @@ -128,6 +131,10 @@ func New( } } +// IsSystemTransaction implements consensus.PoSA, checking whether a transaction is a system +// transaction or not. +// A system transaction is a transaction that has the recipient of the contract address +// is defined in params.ConsortiumV2Contracts func (c *Consortium) IsSystemTransaction(tx *types.Transaction, header *types.Header) (bool, error) { // deploy a contract if tx.To() == nil { @@ -143,6 +150,9 @@ func (c *Consortium) IsSystemTransaction(tx *types.Transaction, header *types.He return false, nil } +// IsSystemContract implements consensus.PoSA, checking whether a contract is a system +// contract or not +// A system contract is a contract is defined in params.ConsortiumV2Contracts func (c *Consortium) IsSystemContract(to *common.Address) bool { if to == nil { return false @@ -150,14 +160,18 @@ func (c *Consortium) IsSystemContract(to *common.Address) bool { return c.chainConfig.ConsortiumV2Contracts.IsSystemContract(*to) } +// Author implements consensus.Engine, returning the coinbase directly func (c *Consortium) Author(header *types.Header) (common.Address, error) { return header.Coinbase, nil } +// VerifyHeader checks whether a header conforms to the consensus rules. func (c *Consortium) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { return c.VerifyHeaderAndParents(chain, header, nil) } +// VerifyHeaders implements consensus.Engine, always returning an empty abort and results channels. +// This method will be handled consortium/main.go instead func (c *Consortium) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { abort := make(chan struct{}) results := make(chan error, len(headers)) @@ -165,10 +179,16 @@ func (c *Consortium) VerifyHeaders(chain consensus.ChainHeaderReader, headers [] return abort, results } +// GetRecents implements common.ConsortiumAdapter, always returning nil +// as this consensus mechanism doesn't need to get recents func (c *Consortium) GetRecents(chain consensus.ChainHeaderReader, number uint64) map[uint64]common.Address { return nil } +// VerifyHeaderAndParents checks whether a header conforms to the consensus rules.The +// caller may optionally pass in a batch of parents (ascending order) to avoid +// looking those up from the database. This is useful for concurrently verifying +// a batch of new headers. func (c *Consortium) VerifyHeaderAndParents(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error { if header.Number == nil { return consortiumCommon.ErrUnknownBlock @@ -186,7 +206,7 @@ func (c *Consortium) VerifyHeaderAndParents(chain consensus.ChainHeaderReader, h if len(header.Extra) < extraVanity+extraSeal { return consortiumCommon.ErrMissingSignature } - // check extra data + // Check extra data isEpoch := number%c.config.Epoch == 0 || c.chainConfig.IsOnConsortiumV2(header.Number) // Ensure that the extra-data contains a signer list on checkpoint, but none otherwise @@ -221,6 +241,10 @@ func (c *Consortium) VerifyHeaderAndParents(chain consensus.ChainHeaderReader, h return c.verifyCascadingFields(chain, header, parents) } +// verifyCascadingFields verifies all the header fields that are not standalone, +// rather depend on a batch of previous headers. The caller may optionally pass +// in a batch of parents (ascending order) to avoid looking those up from the +// database. This is useful for concurrently verifying a batch of new headers. func (c *Consortium) verifyCascadingFields(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error { // The genesis block is the always valid dead-end number := header.Number.Uint64() @@ -257,6 +281,7 @@ func (c *Consortium) verifyCascadingFields(chain consensus.ChainHeaderReader, he return c.verifySeal(chain, header, parents) } +// snapshot retrieves the authorization snapshot at a given point in time. func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64, hash common.Hash, parents []*types.Header) (*Snapshot, error) { if err := c.initContract(); err != nil { return nil, err @@ -265,7 +290,7 @@ func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64, var ( headers []*types.Header snap *Snapshot - // @linh: We must copy parents before going to the loop because parents are modified. + // NOTE(linh): We must copy parents before going to the loop because parents are modified. // If not, the FindAncientHeader function can not find its block ancestor cpyParents = parents ) @@ -281,9 +306,9 @@ func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64, if number%c.config.Epoch == 0 { var err error - // @linh: In case the snapshot of hardfork - 1 is requested, we find the latest snapshot in the last - // checkpoint of v1. We need to use the correct load snapshot version to load the snapshot coming - // from v1. + // NOTE(linh): In case the snapshot of hardfork - 1 is requested, we find the latest snapshot + // in the last checkpoint of v1. We need to use the correct load snapshot version + // to load the snapshot coming from v1. if !c.chainConfig.IsConsortiumV2(common.Big0.SetUint64(number)) { snap, err = loadSnapshotV1(c.config, c.signatures, c.db, hash, c.ethAPI, c.chainConfig) } else { @@ -297,8 +322,8 @@ func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64, if err == nil { log.Trace("Loaded snapshot from disk", "number", number, "hash", hash.Hex()) if !c.chainConfig.IsConsortiumV2(common.Big0.SetUint64(snap.Number)) { - // @linh: In version 1, the snapshot is not used correctly, so we must clean up incorrect data in - // the recent list before going to version 2 + // NOTE(linh): In version 1, the snapshot is not used correctly, so we must clean up + // incorrect data in the recent list before going to version 2 // // Example: The current block is 1000, and the recents list is // [2: address1, 3: address2, ...,998: addressN - 1,999: addressN] @@ -359,6 +384,8 @@ func (c *Consortium) snapshot(chain consensus.ChainHeaderReader, number uint64, return snap, err } +// VerifyUncles implements consensus.Engine, always returning an error for any +// uncles as this consensus mechanism doesn't permit uncles. func (c *Consortium) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { if len(block.Uncles()) > 0 { return errors.New("uncles not allowed") @@ -419,6 +446,8 @@ func (c *Consortium) verifySeal(chain consensus.ChainHeaderReader, header *types return nil } +// Prepare implements consensus.Engine, preparing all the consensus fields of the +// header for running the transactions on top. func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { if err := c.initContract(); err != nil { return err @@ -449,14 +478,14 @@ func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.He if err != nil { return err } - // sort validator by address + // Sort validators by address sort.Sort(validatorsAscending(newValidators)) for _, validator := range newValidators { header.Extra = append(header.Extra, validator.Bytes()...) } } - // add extra seal space + // Add extra seal space header.Extra = append(header.Extra, make([]byte, extraSeal)...) // Mix digest is reserved for now, set to empty @@ -474,12 +503,16 @@ func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.He return nil } +// Finalize implements consensus.Engine that calls three methods from smart contracts: +// - WrapUpEpoch at epoch to distribute rewards and sort the validators set +// - Slash the validator who does not sign if it is in-turn +// - SubmitBlockRewards of the current block func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs *[]*types.Transaction, uncles []*types.Header, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction, usedGas *uint64) error { if err := c.initContract(); err != nil { return err } - // warn if not in majority fork + number := header.Number.Uint64() snap, err := c.snapshot(chain, number-1, header.ParentHash, nil) if err != nil { @@ -492,8 +525,10 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H ChainConfig: c.chainConfig, ChainContext: consortiumCommon.ChainContext{Chain: chain, Consortium: c}, }, - Txs: txs, - Receipts: receipts, + Txs: txs, + Receipts: receipts, + // a.k.a. System Txs + // systemTxs is received from other nodes ReceivedTxs: systemTxs, UsedGas: usedGas, Mining: false, @@ -502,7 +537,7 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H EthAPI: c.ethAPI, } - // If the block is a epoch end block, verify the validator list + // If the block is an epoch end block, verify the validator list // The verification can only be done when the state is ready, it can't be done in VerifyHeader. if header.Number.Uint64()%c.config.Epoch == 0 { // The GetValidators in Prepare is called on the context of previous block so here it must @@ -551,8 +586,7 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H } } - err = c.contract.SubmitBlockReward(transactOpts) - if err != nil { + if err = c.contract.SubmitBlockReward(transactOpts); err != nil { return err } if len(*systemTxs) > 0 { @@ -561,6 +595,10 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H return nil } +// FinalizeAndAssemble implements consensus.Engine that calls three methods from smart contracts: +// - WrapUpEpoch at epoch to distribute rewards and sort the validators set +// - Slash the validator who does not sign if it is in-turn +// - SubmitBlockRewards of the current block func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) { if err := c.initContract(); err != nil { @@ -582,8 +620,10 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head ChainConfig: c.chainConfig, ChainContext: consortiumCommon.ChainContext{Chain: chain, Consortium: c}, }, - Txs: &txs, - Receipts: &receipts, + Txs: &txs, + Receipts: &receipts, + // a.k.a. System Txs + // It always equals nil since FinalizeAndAssemble doesn't receive any transactions ReceivedTxs: nil, UsedGas: &header.GasUsed, Mining: true, @@ -607,7 +647,7 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head if !signedRecently { err = c.contract.Slash(transactOpts, spoiledVal) if err != nil { - // it is possible that slash validator failed because of the slash channel is disabled. + // It is possible that slash validator failed because of the slash channel is disabled. log.Error("Slash validator failed", "block hash", header.Hash(), "address", spoiledVal, "error", err) return nil, nil, err } @@ -621,8 +661,7 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head } } - err := c.contract.SubmitBlockReward(transactOpts) - if err != nil { + if err := c.contract.SubmitBlockReward(transactOpts); err != nil { return nil, nil, err } // should not happen. Once happen, stop the node is better than broadcast the block @@ -648,6 +687,7 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head return blk, *transactOpts.Receipts, nil } +// Authorize injects a private key into the consensus engine to mint new blocks with func (c *Consortium) Authorize(signer common.Address, signFn consortiumCommon.SignerFn, signTxFn consortiumCommon.SignerTxFn) { c.lock.Lock() defer c.lock.Unlock() @@ -657,6 +697,8 @@ func (c *Consortium) Authorize(signer common.Address, signFn consortiumCommon.Si c.signTxFn = signTxFn } +// Delay implements consensus.Engine, returning the max duration the miner can commit txs. +// Related issue: https://skymavis.atlassian.net/browse/RON-273 func (c *Consortium) Delay(chain consensus.ChainReader, header *types.Header) *time.Duration { number := header.Number.Uint64() snap, err := c.snapshot(chain, number-1, header.ParentHash, nil) @@ -672,6 +714,8 @@ func (c *Consortium) Delay(chain consensus.ChainReader, header *types.Header) *t return &delay } +// Seal implements consensus.Engine, attempting to create a sealed block using +// the local signing credentials. func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { header := block.Header() @@ -748,18 +792,25 @@ func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, return nil } +// SealHash returns the hash of a block prior to it being sealed. func (c *Consortium) SealHash(header *types.Header) common.Hash { return SealHash(header, c.chainConfig.ChainID) } +// Close implements consensus.Engine. It's a noop for Consortium as there are no background threads. func (c *Consortium) Close() error { return nil } +// APIs are backward compatible with the v1, so we do not to implement it again func (c *Consortium) APIs(chain consensus.ChainHeaderReader) []rpc.API { return []rpc.API{} } +// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty +// that a new block should have: +// * DIFF_NOTURN(3) if (BLOCK_NUMBER + 1) / VALIDATOR_COUNT != VALIDATOR_INDEX +// * DIFF_INTURN(7) if (BLOCK_NUMBER + 1) / VALIDATOR_COUNT == VALIDATOR_INDEX func (c *Consortium) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { snap, err := c.snapshot(chain, parent.Number.Uint64(), parent.Hash(), nil) if err != nil { @@ -770,7 +821,7 @@ func (c *Consortium) CalcDifficulty(chain consensus.ChainHeaderReader, time uint // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty // that a new block should have based on the previous blocks in the chain and the -// current signer. +// current validator. func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int { if snap.inturn(signer) { return new(big.Int).Set(diffInTurn) @@ -778,6 +829,7 @@ func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int { return new(big.Int).Set(diffNoTurn) } +// initContract creates NewContractIntegrator instance func (c *Consortium) initContract() error { contract, err := consortiumCommon.NewContractIntegrator(c.chainConfig, consortiumCommon.NewConsortiumBackend(c.ethAPI), c.signTxFn, c.val) if err != nil { @@ -788,7 +840,7 @@ func (c *Consortium) initContract() error { return nil } -// ecrecover extracts the Ethereum account address from a signed header. +// ecrecover extracts the Ronin account address from a signed header. func ecrecover(header *types.Header, sigcache *lru.ARCCache, chainId *big.Int) (common.Address, error) { // If the signature's already cached, return that hash := header.Hash() @@ -834,6 +886,9 @@ func consortiumRLP(header *types.Header, chainId *big.Int) []byte { return b.Bytes() } +// encodeSigHeader encodes the whole header with chainId. +// chainID was introduced in EIP-155 to prevent replay attacks between the main ETH and ETC chains, +// which both have a networkID of 1 func encodeSigHeader(w io.Writer, header *types.Header, chainId *big.Int) { err := rlp.Encode(w, []interface{}{ chainId, diff --git a/consensus/consortium/v2/consortiumv2fork.go b/consensus/consortium/v2/consortiumv2fork.go index 37d144c8f8..221c8d4875 100644 --- a/consensus/consortium/v2/consortiumv2fork.go +++ b/consensus/consortium/v2/consortiumv2fork.go @@ -25,6 +25,7 @@ func (c *Consortium) delayForConsortiumV2Fork(snap *Snapshot, header *types.Head return delay } +// Ensure the timestamp has the correct delay func (c *Consortium) blockTimeForConsortiumV2Fork(snap *Snapshot, header, parent *types.Header) uint64 { blockTime := parent.Time + c.config.Period return blockTime diff --git a/consensus/consortium/v2/snapshot.go b/consensus/consortium/v2/snapshot.go index 26d5c52cff..96c2763767 100644 --- a/consensus/consortium/v2/snapshot.go +++ b/consensus/consortium/v2/snapshot.go @@ -17,6 +17,7 @@ import ( lru "github.com/hashicorp/golang-lru" ) +// Snapshot is the state of the authorization validators at a given point in time. type Snapshot struct { chainConfig *params.ChainConfig config *params.ConsortiumConfig // Consensus engine parameters to fine tune behavior @@ -36,6 +37,9 @@ func (s validatorsAscending) Len() int { return len(s) } func (s validatorsAscending) Less(i, j int) bool { return bytes.Compare(s[i][:], s[j][:]) < 0 } func (s validatorsAscending) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +// newSnapshot creates a new snapshot with the specified startup parameters. This +// method does not initialize the set of recent validators, so only ever use if for +// the genesis block func newSnapshot(config *params.ConsortiumConfig, sigcache *lru.ARCCache, number uint64, hash common.Hash, validators []common.Address, ethAPI *ethapi.PublicBlockChainAPI) *Snapshot { snap := &Snapshot{ config: config, @@ -52,6 +56,8 @@ func newSnapshot(config *params.ConsortiumConfig, sigcache *lru.ARCCache, number return snap } +// loadSnapshotV1 loads an existing snapshot of v1 from the database +// and convert it into v2 for backward compatible func loadSnapshotV1( config *params.ConsortiumConfig, sigcache *lru.ARCCache, @@ -84,6 +90,7 @@ func loadSnapshotV1( return snapV2, nil } +// loadSnapshot loads an existing snapshot from the database. func loadSnapshot( config *params.ConsortiumConfig, sigcache *lru.ARCCache, @@ -108,6 +115,7 @@ func loadSnapshot( return snap, nil } +// store inserts the snapshot into the database. func (s *Snapshot) store(db ethdb.Database) error { blob, err := json.Marshal(s) if err != nil { @@ -116,6 +124,7 @@ func (s *Snapshot) store(db ethdb.Database) error { return db.Put(append([]byte("consortium-"), s.Hash[:]...), blob) } +// copy creates a deep copy of the snapshot. func (s *Snapshot) copy() *Snapshot { cpy := &Snapshot{ chainConfig: s.chainConfig, @@ -137,6 +146,8 @@ func (s *Snapshot) copy() *Snapshot { return cpy } +// apply creates a new authorization snapshot by applying the given headers to +// the original one. func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderReader, parents []*types.Header, chainId *big.Int) (*Snapshot, error) { // Allow passing in no headers for cleaner code if len(headers) == 0 { @@ -160,10 +171,13 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea // Iterate through the headers and create a new snapshot snap := s.copy() + // Number of consecutive blocks out of which a validator may only sign one. + // Must be len(snap.Validators)/2 + 1 to enforce majority consensus on a chain + validatorLimit := len(snap.Validators)/2 + 1 for _, header := range headers { number := header.Number.Uint64() - // Delete the oldest validator from the recent list to allow it signing again - if limit := uint64(len(snap.Validators)/2 + 1); number >= limit { + // Delete the oldest validators from the recent list to allow it signing again + if limit := uint64(validatorLimit); number >= limit { delete(snap.Recents, number-limit) } // Resolve the authorization key and check against signers @@ -190,15 +204,16 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea } } snap.Recents[number] = validator - // change validator set + // Change the validator set base on the size of the validators set if number > 0 && number%s.config.Epoch == uint64(len(snap.Validators)/2) { + // Get the most recent checkpoint header checkpointHeader := FindAncientHeader(header, uint64(len(snap.Validators)/2), chain, parents) if checkpointHeader == nil { return nil, consensus.ErrUnknownAncestor } validatorBytes := checkpointHeader.Extra[extraVanity : len(checkpointHeader.Extra)-extraSeal] - // get validators from headers and use that for new validator set + // Get validator set from headers and use that for new validator set newValArr, err := ParseValidators(validatorBytes) if err != nil { return nil, err @@ -207,7 +222,7 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea for _, val := range newValArr { newVals[val] = struct{}{} } - oldLimit := len(snap.Validators)/2 + 1 + oldLimit := validatorLimit newLimit := len(newVals)/2 + 1 if newLimit < oldLimit { for i := 0; i < oldLimit-newLimit; i++ { @@ -239,12 +254,14 @@ func (s *Snapshot) inturn(validator common.Address) bool { return validators[offset] == validator } +// supposeValidator returns the in-turn validator at a given block height func (s *Snapshot) supposeValidator() common.Address { validators := s.validators() index := (s.Number + 1) % uint64(len(validators)) return validators[index] } +// ParseValidators retrieves the list of validators func ParseValidators(validatorsBytes []byte) ([]common.Address, error) { if len(validatorsBytes)%validatorBytesLength != 0 { return nil, errors.New("invalid validators bytes") @@ -259,6 +276,13 @@ func ParseValidators(validatorsBytes []byte) ([]common.Address, error) { return result, nil } +// FindAncientHeader finds the most recent checkpoint header +// Travel through the candidateParents to find the ancient header. +// If all headers in candidateParents have the number is larger than the header number, +// the search function will return the index, but it is not valid if we check with the +// header since the number and hash is not equals. The candidateParents is +// only available when it downloads blocks from the network. +// Otherwise, the candidateParents is nil, and it will be found by header hash and number. func FindAncientHeader(header *types.Header, ite uint64, chain consensus.ChainHeaderReader, candidateParents []*types.Header) *types.Header { ancient := header for i := uint64(1); i <= ite; i++ { From c140273344a44ac6a8712bda34739d01904cd072 Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Wed, 12 Oct 2022 11:37:07 +0700 Subject: [PATCH 46/52] [RON-276] docs(consortium-main): add code comment, remove unused constant (#141) * docs(consortium-main): add code comment, remove unused ValidatorBytesLength constant * docs(consortium-main): fix typo --- consensus/consortium/common/constants.go | 5 +--- consensus/consortium/common/context.go | 4 ++++ consensus/consortium/common/types.go | 6 +++-- consensus/consortium/common/utils.go | 1 + consensus/consortium/main.go | 30 ++++++++++++++++++++---- consensus/consortium/v2/consortium.go | 4 ++-- 6 files changed, 37 insertions(+), 13 deletions(-) diff --git a/consensus/consortium/common/constants.go b/consensus/consortium/common/constants.go index 5cf4ed5afc..4106219042 100644 --- a/consensus/consortium/common/constants.go +++ b/consensus/consortium/common/constants.go @@ -2,13 +2,10 @@ package common import ( "errors" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" ) -const ValidatorBytesLength = common.AddressLength - -var ( +const ( ExtraSeal = crypto.SignatureLength // Fixed number of extra-data suffix bytes reserved for signer seal ) diff --git a/consensus/consortium/common/context.go b/consensus/consortium/common/context.go index c1b1cea284..b0a9e0eab4 100644 --- a/consensus/consortium/common/context.go +++ b/consensus/consortium/common/context.go @@ -6,15 +6,19 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) +// ChainContext supports retrieving headers and consensus parameters from the +// current blockchain to be used during transaction processing. type ChainContext struct { Chain consensus.ChainHeaderReader Consortium consensus.Engine } +// Engine retrieves the chain's consensus engine. func (c ChainContext) Engine() consensus.Engine { return c.Consortium } +// GetHeader returns the hash corresponding to their hash. func (c ChainContext) GetHeader(hash common.Hash, number uint64) *types.Header { return c.Chain.GetHeader(hash, number) } diff --git a/consensus/consortium/common/types.go b/consensus/consortium/common/types.go index ede8ca5aef..ac9064fbec 100644 --- a/consensus/consortium/common/types.go +++ b/consensus/consortium/common/types.go @@ -8,12 +8,14 @@ import ( "math/big" ) -// SignerFn is a signer callback function to request a header to be signed by a -// backing account. +// SignerFn is a signer callback function to request the wallet to sign the hash of the given data type SignerFn func(accounts.Account, string, []byte) ([]byte, error) +// SignerTxFn is a signer callback function to request the wallet to sign the given transaction. type SignerTxFn func(accounts.Account, *types.Transaction, *big.Int) (*types.Transaction, error) +// ConsortiumAdapter defines a small collection of methods needed to access the private +// methods between consensus engines type ConsortiumAdapter interface { GetRecents(chain consensus.ChainHeaderReader, number uint64) map[uint64]common.Address } diff --git a/consensus/consortium/common/utils.go b/consensus/consortium/common/utils.go index a65acf7b6f..dbbdf8cdf0 100644 --- a/consensus/consortium/common/utils.go +++ b/consensus/consortium/common/utils.go @@ -32,6 +32,7 @@ func CompareSignersLists(list1 []common.Address, list2 []common.Address) bool { return true } +// SignerInList checks the given signer address is whether in the validators set or not func SignerInList(signer common.Address, validators []common.Address) bool { for _, validator := range validators { if signer == validator { diff --git a/consensus/consortium/main.go b/consensus/consortium/main.go index e1d8c5b0a0..02230a9223 100644 --- a/consensus/consortium/main.go +++ b/consensus/consortium/main.go @@ -17,14 +17,15 @@ import ( "github.com/ethereum/go-ethereum/rpc" ) +// Consortium is a proxy that decides the consensus version will be called +// based on params.ConsortiumV2Block type Consortium struct { chainConfig *params.ChainConfig v1 *v1.Consortium v2 *v2.Consortium } -// New creates a Consortium proof-of-stake consensus engine with the initial -// signers set to the ones provided by the user. +// New creates a Consortium proxy that decides what Consortium version will be called func New(chainConfig *params.ChainConfig, db ethdb.Database, ee *ethapi.PublicBlockChainAPI, genesisHash common.Hash) *Consortium { // Set any missing consensus parameters to their defaults consortiumV1 := v1.New(chainConfig, db, ee) @@ -37,6 +38,7 @@ func New(chainConfig *params.ChainConfig, db ethdb.Database, ee *ethapi.PublicBl } } +// Author implements consensus.Engine, returning the coinbase directly func (c *Consortium) Author(header *types.Header) (common.Address, error) { if c.chainConfig.IsConsortiumV2(header.Number) { return c.v2.Author(header) @@ -45,6 +47,7 @@ func (c *Consortium) Author(header *types.Header) (common.Address, error) { return c.v1.Author(header) } +// VerifyHeader checks whether a header conforms to the consensus rules. func (c *Consortium) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { if c.chainConfig.IsConsortiumV2(header.Number) { return c.v2.VerifyHeader(chain, header, seal) @@ -53,6 +56,9 @@ func (c *Consortium) VerifyHeader(chain consensus.ChainHeaderReader, header *typ return c.v1.VerifyHeader(chain, header, seal) } +// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers. The +// method returns a quit channel to abort the operations and a results channel to +// retrieve the async verifications (the order is that of the input slice). func (c *Consortium) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { abort := make(chan struct{}) results := make(chan error, len(headers)) @@ -77,6 +83,8 @@ func (c *Consortium) VerifyHeaders(chain consensus.ChainHeaderReader, headers [] return abort, results } +// VerifyUncles implements consensus.Engine, always returning an error for any +// uncles as this consensus mechanism doesn't permit uncles. func (c *Consortium) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { if c.chainConfig.IsConsortiumV2(block.Header().Number) { return c.v2.VerifyUncles(chain, block) @@ -85,6 +93,8 @@ func (c *Consortium) VerifyUncles(chain consensus.ChainReader, block *types.Bloc return c.v1.VerifyUncles(chain, block) } +// Prepare implements consensus.Engine, preparing all the consensus fields of the +// header for running the transactions on top. func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { if c.chainConfig.IsConsortiumV2(header.Number) { return c.v2.Prepare(chain, header) @@ -93,6 +103,7 @@ func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.He return c.v1.Prepare(chain, header) } +// Finalize implements consensus.Engine as a proxy func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs *[]*types.Transaction, uncles []*types.Header, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction, usedGas *uint64) error { if c.chainConfig.IsConsortiumV2(header.Number) { @@ -102,6 +113,7 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H return c.v1.Finalize(chain, header, state, txs, uncles, receipts, systemTxs, usedGas) } +// FinalizeAndAssemble implements consensus.Engine as a proxy func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) { if c.chainConfig.IsConsortiumV2(header.Number) { @@ -111,6 +123,9 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head return c.v1.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts) } +// Delay implements consensus.Engine as a proxy, returning the max duration the miner can commit txs. +// It decides what Consortium version will be called +// Related issue: https://skymavis.atlassian.net/browse/RON-273 func (c *Consortium) Delay(chain consensus.ChainReader, header *types.Header) *time.Duration { if c.chainConfig.IsConsortiumV2(header.Number) { return c.v2.Delay(chain, header) @@ -119,6 +134,8 @@ func (c *Consortium) Delay(chain consensus.ChainReader, header *types.Header) *t return c.v1.Delay(chain, header) } +// Seal implements consensus.Engine, attempting to create a sealed block using +// the local signing credentials. func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { if c.chainConfig.IsConsortiumV2(block.Header().Number) { return c.v2.Seal(chain, block, results, stop) @@ -127,6 +144,7 @@ func (c *Consortium) Seal(chain consensus.ChainHeaderReader, block *types.Block, return c.v1.Seal(chain, block, results, stop) } +// SealHash returns the hash of a block prior to it being sealed. func (c *Consortium) SealHash(header *types.Header) common.Hash { if c.chainConfig.IsConsortiumV2(header.Number) { return c.v2.SealHash(header) @@ -135,8 +153,7 @@ func (c *Consortium) SealHash(header *types.Header) common.Hash { return c.v1.SealHash(header) } -// Close since v1 and v2 are implemented the same logic, so we don't need to check whether the current block is version 1 -// or version 2 +// Close implements consensus.Engine. It's a noop for Consortium as there are no background threads. func (c *Consortium) Close() error { return nil } @@ -153,6 +170,7 @@ func (c *Consortium) APIs(chain consensus.ChainHeaderReader) []rpc.API { return apis } +// CalcDifficulty is the difficulty adjustment algorithm func (c *Consortium) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { if c.chainConfig.IsConsortiumV2(parent.Number) { return c.v2.CalcDifficulty(chain, time, parent) @@ -161,7 +179,7 @@ func (c *Consortium) CalcDifficulty(chain consensus.ChainHeaderReader, time uint return c.v1.CalcDifficulty(chain, time, parent) } -// Authorize backward compatible for consortium v1 +// Authorize injects a private key into the consensus engine to mint new blocks with func (c *Consortium) Authorize(signer common.Address, signFn consortiumCommon.SignerFn, signTxFn consortiumCommon.SignerTxFn) { c.v1.Authorize(signer, signFn, signTxFn) c.v2.Authorize(signer, signFn, signTxFn) @@ -177,10 +195,12 @@ func (c *Consortium) SetGetFenixValidators(fn func() ([]common.Address, error)) c.v1.SetGetFenixValidators(fn) } +// IsSystemTransaction implements consensus.PoSA. It is only available on v2 since v1 doesn't have system contract func (c *Consortium) IsSystemTransaction(tx *types.Transaction, header *types.Header) (bool, error) { return c.v2.IsSystemTransaction(tx, header) } +// IsSystemContract implements consensus.PoSA. It is only available on v2 since v1 doesn't have system contract func (c *Consortium) IsSystemContract(to *common.Address) bool { return c.v2.IsSystemContract(to) } diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index e0a039d20b..9348bcc034 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -215,7 +215,7 @@ func (c *Consortium) VerifyHeaderAndParents(chain consensus.ChainHeaderReader, h return consortiumCommon.ErrExtraValidators } - if isEpoch && signersBytes%consortiumCommon.ValidatorBytesLength != 0 { + if isEpoch && signersBytes%common.AddressLength != 0 { return consortiumCommon.ErrInvalidSpanValidators } @@ -904,7 +904,7 @@ func encodeSigHeader(w io.Writer, header *types.Header, chainId *big.Int) { header.GasLimit, header.GasUsed, header.Time, - header.Extra[:len(header.Extra)-crypto.SignatureLength], // Yes, this will panic if extra is too short + header.Extra[:len(header.Extra)-consortiumCommon.ExtraSeal], // Yes, this will panic if extra is too short header.MixDigest, header.Nonce, }) From 5f1499c6bb2819ab03256c0ad7fd6586bd6b687f Mon Sep 17 00:00:00 2001 From: minh-bq <97180373+minh-bq@users.noreply.github.com> Date: Thu, 13 Oct 2022 14:01:14 +0700 Subject: [PATCH 47/52] Append RONIN_PARAMS in case non-standard network id (#150) --- docker/chainnode/entrypoint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/chainnode/entrypoint.sh b/docker/chainnode/entrypoint.sh index f70096b758..1b9d335435 100755 --- a/docker/chainnode/entrypoint.sh +++ b/docker/chainnode/entrypoint.sh @@ -46,7 +46,7 @@ if [[ ! -z $NETWORK_ID ]]; then echo "network id not supported" ;; esac - params="$params --networkid $NETWORK_ID" + params="$params --networkid $NETWORK_ID $RONIN_PARAMS" fi # custom genesis path From 5c1b212859459a61ce0162a51bdf5cb935cc1328 Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Fri, 14 Oct 2022 13:14:45 +0700 Subject: [PATCH 48/52] [RON-299] fix: update sortSC precompiled requirements (#151) * fix: align precompiled requirements * test: update TestConsortiumValidatorSorting_Run2 * test: update compiled code * chore(precompiled): update consortiumValidatorSorting comments --- core/vm/consortium_precompiled_contracts.go | 51 ++- .../consortium_precompiled_contracts_test.go | 319 ++++++++++++------ 2 files changed, 243 insertions(+), 127 deletions(-) diff --git a/core/vm/consortium_precompiled_contracts.go b/core/vm/consortium_precompiled_contracts.go index 55f0fa13b1..2da7c91e0f 100644 --- a/core/vm/consortium_precompiled_contracts.go +++ b/core/vm/consortium_precompiled_contracts.go @@ -21,7 +21,7 @@ import ( var ( consortiumLogAbi = `[{"inputs":[{"internalType":"string","name":"message","type":"string"}],"name":"log","outputs":[],"stateMutability":"nonpayable","type":"function"}]` - consortiumSortValidatorAbi = `[{"inputs":[],"name":"getValidatorCandidates","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"sortValidators","outputs":[{"internalType":"address[]","name":"validators","type":"address[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_poolList","type":"address[]"}],"name":"totalBalances","outputs":[{"internalType":"uint256[]","name":"_balances","type":"uint256[]"}],"stateMutability":"view","type":"function"}]` + consortiumSortValidatorAbi = `[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address[]","name":"validators","type":"address[]"},{"internalType":"uint256[]","name":"weights","type":"uint256[]"}],"name":"sortValidators","outputs":[{"internalType":"address[]","name":"_validators","type":"address[]"}],"stateMutability":"view","type":"function"}]` consortiumVerifyHeadersAbi = `[{"outputs":[],"name":"getHeader","inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"bytes32","name":"parentHash","type":"bytes32"},{"internalType":"bytes32","name":"ommersHash","type":"bytes32"},{"internalType":"address","name":"coinbase","type":"address"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"internalType":"bytes32","name":"transactionsRoot","type":"bytes32"},{"internalType":"bytes32","name":"receiptsRoot","type":"bytes32"},{"internalType":"uint8[256]","name":"logsBloom","type":"uint8[256]"},{"internalType":"uint256","name":"difficulty","type":"uint256"},{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint64","name":"gasLimit","type":"uint64"},{"internalType":"uint64","name":"gasUsed","type":"uint64"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"bytes","name":"extraData","type":"bytes"},{"internalType":"bytes32","name":"mixHash","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"header1","type":"bytes"},{"internalType":"bytes","name":"header2","type":"bytes"}],"name":"validatingDoubleSignProof","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]` ) @@ -86,42 +86,37 @@ func (c *consortiumValidatorSorting) Run(input []byte) ([]byte, error) { return nil, errors.New("unauthorized sender") } // get method, args from abi - smcAbi, method, args, err := loadMethodAndArgs(consortiumSortValidatorAbi, input) + _, method, args, err := loadMethodAndArgs(consortiumSortValidatorAbi, input) if err != nil { return nil, err } if method.Name != sortValidatorsMethod { return nil, errors.New("invalid method") } - if len(args) != 1 { - return nil, errors.New(fmt.Sprintf("invalid arguments, expected 1 got %d", len(args))) + if len(args) != 2 { + return nil, errors.New(fmt.Sprintf("invalid arguments, expected 2 got %d", len(args))) } - // cast args[0] to number - limit, ok := args[0].(*big.Int) + // cast args[0] to list addresses + validators, ok := args[0].([]common.Address) if !ok { - return nil, errors.New("invalid argument type") - } - validators, err := loadValidators(c.evm, smcAbi, c.caller.Address()) - if err != nil { - return nil, err - } - totalBalances, err := loadTotalBalances(c.evm, smcAbi, c.caller.Address(), validators) - if err != nil { - return nil, err + return nil, errors.New("invalid first argument type") } - if len(validators) != len(totalBalances) { - return nil, errors.New("balances and validators length mismatched") + + // cast args[1] to list big int + weights, ok := args[1].([]*big.Int) + if !ok { + return nil, errors.New("invalid second argument type") } - sortValidators(validators, totalBalances) - if limit.Int64() > int64(len(validators)) { - limit = big.NewInt(int64(len(validators))) + if len(validators) != len(weights) { + return nil, errors.New("balances and validators length mismatched") } + sortValidators(validators, weights) - return method.Outputs.Pack(validators[:limit.Int64()]) + return method.Outputs.Pack(validators) } -func sortValidators(validators []common.Address, balances []*big.Int) { +func sortValidators(validators []common.Address, weights []*big.Int) { if len(validators) < 2 { return } @@ -131,23 +126,23 @@ func sortValidators(validators []common.Address, balances []*big.Int) { pivot := rand.Int() % len(validators) validators[pivot], validators[right] = validators[right], validators[pivot] - balances[pivot], balances[right] = balances[right], balances[pivot] + weights[pivot], weights[right] = weights[right], weights[pivot] for i, _ := range validators { - cmp := balances[i].Cmp(balances[right]) + cmp := weights[i].Cmp(weights[right]) addrsCmp := big.NewInt(0).SetBytes(validators[i].Bytes()).Cmp(big.NewInt(0).SetBytes(validators[right].Bytes())) > 0 if cmp > 0 || (cmp == 0 && addrsCmp) { validators[left], validators[i] = validators[i], validators[left] - balances[left], balances[i] = balances[i], balances[left] + weights[left], weights[i] = weights[i], weights[left] left++ } } validators[left], validators[right] = validators[right], validators[left] - balances[left], balances[right] = balances[right], balances[left] + weights[left], weights[right] = weights[right], weights[left] - sortValidators(validators[:left], balances[:left]) - sortValidators(validators[left+1:], balances[left+1:]) + sortValidators(validators[:left], weights[:left]) + sortValidators(validators[left+1:], weights[left+1:]) return } diff --git a/core/vm/consortium_precompiled_contracts_test.go b/core/vm/consortium_precompiled_contracts_test.go index 061e3abc46..917da78767 100644 --- a/core/vm/consortium_precompiled_contracts_test.go +++ b/core/vm/consortium_precompiled_contracts_test.go @@ -16,136 +16,255 @@ import ( "testing" ) -/** +/* +* testSortCodes is generated based on the following code ``` // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0 <0.9.0; -contract Validators { - address[] _validators = [ - 0x0000000000000000000000000000000000000010, - 0x0000000000000000000000000000000000000011, - 0x0000000000000000000000000000000000000012, - 0x0000000000000000000000000000000000000013, - 0x0000000000000000000000000000000000000014, - 0x0000000000000000000000000000000000000015, - 0x0000000000000000000000000000000000000016, - 0x0000000000000000000000000000000000000017, - 0x0000000000000000000000000000000000000018, - 0x0000000000000000000000000000000000000019, - 0x0000000000000000000000000000000000000020, - 0x0000000000000000000000000000000000000021, - 0x0000000000000000000000000000000000000022, - 0x0000000000000000000000000000000000000023, - 0x0000000000000000000000000000000000000024, - 0x0000000000000000000000000000000000000025, - 0x0000000000000000000000000000000000000026, - 0x0000000000000000000000000000000000000027, - 0x0000000000000000000000000000000000000028, - 0x0000000000000000000000000000000000000029, - 0x0000000000000000000000000000000000000030 - ]; - uint256[] _totalBalances = [1,4,6,2,8,9,10,3,16,20,100,12,22,30,50,60,5,18,16,22,21]; - constructor() {} - function getValidatorCandidates() public view returns (address[] memory _validatorList) { - _validatorList = _validators; - } - function totalBalances(address[] calldata _poolList) public view returns (uint256[] memory _balances) { - _balances = _totalBalances; - } -} + contract Validators { + address[] _validators = [ + 0x0000000000000000000000000000000000000010, + 0x0000000000000000000000000000000000000011, + 0x0000000000000000000000000000000000000012, + 0x0000000000000000000000000000000000000013, + 0x0000000000000000000000000000000000000014, + 0x0000000000000000000000000000000000000015, + 0x0000000000000000000000000000000000000016, + 0x0000000000000000000000000000000000000017, + 0x0000000000000000000000000000000000000018, + 0x0000000000000000000000000000000000000019, + 0x0000000000000000000000000000000000000020, + 0x0000000000000000000000000000000000000021, + 0x0000000000000000000000000000000000000022, + 0x0000000000000000000000000000000000000023, + 0x0000000000000000000000000000000000000024, + 0x0000000000000000000000000000000000000025, + 0x0000000000000000000000000000000000000026, + 0x0000000000000000000000000000000000000027, + 0x0000000000000000000000000000000000000028, + 0x0000000000000000000000000000000000000029, + 0x0000000000000000000000000000000000000030 + ]; + uint256[] _totalBalances = [1,4,6,2,8,9,10,3,16,20,100,12,22,30,50,60,5,18,16,22,21]; + constructor() {} + function getValidatorCandidates() public view returns (address[] memory _validatorList) { + _validatorList = _validators; + } + function totalBalances(address[] calldata _poolList) public view returns (uint256[] memory _balances) { + _balances = _totalBalances; + } + } + ``` */ var testSortCode = `6080604052604051806102a00160405280601073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001601173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001601273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001601373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001601473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001601573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001601673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001601773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001601873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001601973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001602073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001602173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001602273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001602373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001602473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001602573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001602673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001602773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001602873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001602973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001603073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250600090601561044d92919061054d565b50604051806102a00160405280600160ff168152602001600460ff168152602001600660ff168152602001600260ff168152602001600860ff168152602001600960ff168152602001600a60ff168152602001600360ff168152602001601060ff168152602001601460ff168152602001606460ff168152602001600c60ff168152602001601660ff168152602001601e60ff168152602001603260ff168152602001603c60ff168152602001600560ff168152602001601260ff168152602001601060ff168152602001601660ff168152602001601560ff16815250600190601561053a9291906105d7565b5034801561054757600080fd5b50610646565b8280548282559060005260206000209081019282156105c6579160200282015b828111156105c55782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509160200191906001019061056d565b5b5090506105d39190610629565b5090565b828054828255906000526020600020908101928215610618579160200282015b82811115610617578251829060ff169055916020019190600101906105f7565b5b5090506106259190610629565b5090565b5b8082111561064257600081600090555060010161062a565b5090565b610460806106556000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80634a5d76cd1461003b578063ba77b06c1461006b575b600080fd5b610055600480360381019061005091906101e1565b610089565b60405161006291906102f6565b60405180910390f35b6100736100e4565b6040516100809190610408565b60405180910390f35b606060018054806020026020016040519081016040528092919081815260200182805480156100d757602002820191906000526020600020905b8154815260200190600101908083116100c3575b5050505050905092915050565b6060600080548060200260200160405190810160405280929190818152602001828054801561016857602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161011e575b5050505050905090565b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b60008083601f8401126101a1576101a061017c565b5b8235905067ffffffffffffffff8111156101be576101bd610181565b5b6020830191508360208202830111156101da576101d9610186565b5b9250929050565b600080602083850312156101f8576101f7610172565b5b600083013567ffffffffffffffff81111561021657610215610177565b5b6102228582860161018b565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000819050919050565b61026d8161025a565b82525050565b600061027f8383610264565b60208301905092915050565b6000602082019050919050565b60006102a38261022e565b6102ad8185610239565b93506102b88361024a565b8060005b838110156102e95781516102d08882610273565b97506102db8361028b565b9250506001810190506102bc565b5085935050505092915050565b600060208201905081810360008301526103108184610298565b905092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061036f82610344565b9050919050565b61037f81610364565b82525050565b60006103918383610376565b60208301905092915050565b6000602082019050919050565b60006103b582610318565b6103bf8185610323565b93506103ca83610334565b8060005b838110156103fb5781516103e28882610385565b97506103ed8361039d565b9250506001810190506103ce565b5085935050505092915050565b6000602082019050818103600083015261042281846103aa565b90509291505056fea26469706673582212204aab6725297603e4a73daf57fffdd55330e60293dfde78dcbbddb9178144583064736f6c63430008110033` -/** +/* +* wrapupCode is used to call sortValidators precompiled contract with the following code ``` // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0 <0.9.0; -contract Wrapup { - constructor() {} - - function sortValidators() public view returns (address[21] memory _validators) { - bytes memory payload = abi.encodeWithSignature("sortValidators(uint256)", 21); - uint payloadLength = payload.length; - address _smc = address(0x66); - assembly { - let payloadStart := add(payload, 32) - if iszero(staticcall(0, _smc, payloadStart, payloadLength, _validators, 0x2e0)) { - revert(0, 0) - } - returndatacopy(_validators, 64, 672) - return(_validators, 672) - } - } -} + contract Wrapup { + constructor() {} + + address[] _validators = [ + 0x0000000000000000000000000000000000000064, + 0x0000000000000000000000000000000000000065, + 0x0000000000000000000000000000000000000066, + 0x0000000000000000000000000000000000000067, + 0x0000000000000000000000000000000000000068, + 0x0000000000000000000000000000000000000069, + 0x000000000000000000000000000000000000006a, + 0x000000000000000000000000000000000000006b, + 0x000000000000000000000000000000000000006C, + 0x000000000000000000000000000000000000006D, + 0x000000000000000000000000000000000000006E, + 0x000000000000000000000000000000000000006F, + 0x0000000000000000000000000000000000000070, + 0x0000000000000000000000000000000000000071, + 0x0000000000000000000000000000000000000072, + 0x0000000000000000000000000000000000000073, + 0x0000000000000000000000000000000000000074, + 0x0000000000000000000000000000000000000075, + 0x0000000000000000000000000000000000000076, + 0x0000000000000000000000000000000000000077, + 0x0000000000000000000000000000000000000078 + ]; + uint256[] _weights = [ + uint256(1000), + uint256(2000), + uint256(3000), + uint256(4000), + uint256(5000), + uint256(6000), + uint256(7000), + uint256(8000), + uint256(9000), + uint256(10000), + uint256(11000), + uint256(12000), + uint256(13000), + uint256(14000), + uint256(15000), + uint256(16000), + uint256(17000), + uint256(18000), + uint256(19000), + uint256(20000), + uint256(21000) + ]; + + function sortValidators() public view returns (address[3] memory _result) { + bytes memory payload = abi.encodeWithSignature( + "sortValidators(address[],uint256[])", + _validators, + _weights + ); + + uint256 payloadLength = payload.length; + uint256 validatorsLength = _validators.length; + uint256 validatorsLengthHex = validatorsLength * 0x20; + uint256 validatorsLengthHex64 = validatorsLength * 0x20 + 64; + address _smc = address(0x66); + + assembly { + let payloadStart := add(payload, 32) + if iszero( + staticcall( + 0, + _smc, + payloadStart, + payloadLength, + _result, + validatorsLengthHex64 + ) + ) { + revert(0, 0) + } + returndatacopy(_result, 64, validatorsLengthHex) + return(_result, validatorsLengthHex) + } + } + } + ``` */ var ( - wrapupCode = `608060405234801561001057600080fd5b506102d8806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c806327167aec14610030575b600080fd5b61003861004e565b6040516100459190610219565b60405180910390f35b610056610119565b6000601560405160240161006a9190610287565b6040516020818303038152906040527f2e73ae11000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600081519050600060669050602083016102e0858483856000fa61010c57600080fd5b6102a06040863e6102a085f35b604051806102a00160405280601590602082028036833780820191505090505090565b600060159050919050565b600081905092915050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101878261015c565b9050919050565b6101978161017c565b82525050565b60006101a9838361018e565b60208301905092915050565b6000602082019050919050565b6101cb8161013c565b6101d58184610147565b92506101e082610152565b8060005b838110156102115781516101f8878261019d565b9650610203836101b5565b9250506001810190506101e4565b505050505050565b60006102a08201905061022f60008301846101c2565b92915050565b6000819050919050565b600060ff82169050919050565b6000819050919050565b600061027161026c61026784610235565b61024c565b61023f565b9050919050565b61028181610256565b82525050565b600060208201905061029c6000830184610278565b9291505056fea2646970667358221220d9e99c6aa93156ae399b93dff44f456409a5715d61d7f761ea1ed96a42bba43864736f6c63430008110033` + wrapupCode = `6080604052604051806102a00160405280606473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001606573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001606673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001606773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001606873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001606973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001606a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001606b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001606c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001606d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001606e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001606f73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001607073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001607173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001607273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001607373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001607473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001607573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001607673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001607773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001607873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250600090601561044d929190610523565b50604051806102a001604052806103e881526020016107d08152602001610bb88152602001610fa0815260200161138881526020016117708152602001611b588152602001611f40815260200161232881526020016127108152602001612af88152602001612ee081526020016132c881526020016136b08152602001613a988152602001613e80815260200161426881526020016146508152602001614a388152602001614e20815260200161520881525060019060156105109291906105ad565b5034801561051d57600080fd5b50610617565b82805482825590600052602060002090810192821561059c579160200282015b8281111561059b5782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555091602001919060010190610543565b5b5090506105a991906105fa565b5090565b8280548282559060005260206000209081019282156105e9579160200282015b828111156105e85782518255916020019190600101906105cd565b5b5090506105f691906105fa565b5090565b5b808211156106135760008160009055506001016105fb565b5090565b6105bc806106266000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c806327167aec14610030575b600080fd5b61003861004e565b60405161004591906102de565b60405180910390f35b61005661014c565b600080600160405160240161006c9291906102fa565b6040516020818303038152906040527f788341af000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060008151905060008080549050905060006020826101099190610430565b90506000604060208461011c9190610430565b61012691906103da565b90506000606690506020860182888783856000fa61014357600080fd5b836040893e8388f35b604051806102a00160405280601590602082028036833780820191505090505090565b600061017b838361019f565b60208301905092915050565b600061019383836102cf565b60208301905092915050565b6101a8816104b4565b82525050565b6101b781610365565b6101c181846103ad565b92506101cc82610331565b8060005b838110156101fd5781516101e4878261016f565b96506101ef83610386565b9250506001810190506101d0565b505050505050565b600061021082610370565b61021a81856103b8565b93506102258361033b565b8060005b8381101561025d5761023a82610553565b610244888261016f565b975061024f83610393565b925050600181019050610229565b5085935050505092915050565b60006102758261037b565b61027f81856103c9565b935061028a83610350565b8060005b838110156102c25761029f82610566565b6102a98882610187565b97506102b4836103a0565b92505060018101905061028e565b5085935050505092915050565b6102d8816104e6565b82525050565b60006102a0820190506102f460008301846101ae565b92915050565b600060408201905081810360008301526103148185610205565b90508181036020830152610328818461026a565b90509392505050565b6000819050919050565b60008190508160005260206000209050919050565b60008190508160005260206000209050919050565b600060159050919050565b600081549050919050565b600081549050919050565b6000602082019050919050565b6000600182019050919050565b6000600182019050919050565b600081905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b60006103e5826104e6565b91506103f0836104e6565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561042557610424610524565b5b828201905092915050565b600061043b826104e6565b9150610446836104e6565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561047f5761047e610524565b5b828202905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006104bf826104c6565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006105036104fe83610579565b61048a565b9050919050565b600061051d61051883610579565b6104aa565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061055f82546104f0565b9050919050565b6000610572825461050a565b9050919050565b60008160001c905091905056fea2646970667358221220bf18e78f84c245c19e8996d9afbcaa3ec60e02e413932b3848d7eed59feb161264736f6c63430008070033` wrapupAbi = `[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"sortValidators","outputs":[{"internalType":"address[21]","name":"_validators","type":"address[21]"}],"stateMutability":"view","type":"function"}]` ) var ( caller = common.BytesToAddress([]byte("sender")) expectedValidators = []common.Address{ - common.HexToAddress("0x0000000000000000000000000000000000000020"), - common.HexToAddress("0x0000000000000000000000000000000000000025"), - common.HexToAddress("0x0000000000000000000000000000000000000024"), - common.HexToAddress("0x0000000000000000000000000000000000000023"), - common.HexToAddress("0x0000000000000000000000000000000000000029"), - common.HexToAddress("0x0000000000000000000000000000000000000022"), - common.HexToAddress("0x0000000000000000000000000000000000000030"), - common.HexToAddress("0x0000000000000000000000000000000000000019"), - common.HexToAddress("0x0000000000000000000000000000000000000027"), - common.HexToAddress("0x0000000000000000000000000000000000000028"), - common.HexToAddress("0x0000000000000000000000000000000000000018"), - common.HexToAddress("0x0000000000000000000000000000000000000021"), - common.HexToAddress("0x0000000000000000000000000000000000000016"), - common.HexToAddress("0x0000000000000000000000000000000000000015"), - common.HexToAddress("0x0000000000000000000000000000000000000014"), - common.HexToAddress("0x0000000000000000000000000000000000000012"), - common.HexToAddress("0x0000000000000000000000000000000000000026"), - common.HexToAddress("0x0000000000000000000000000000000000000011"), - common.HexToAddress("0x0000000000000000000000000000000000000017"), - common.HexToAddress("0x0000000000000000000000000000000000000013"), - common.HexToAddress("0x0000000000000000000000000000000000000010"), + common.BytesToAddress([]byte{120}), + common.BytesToAddress([]byte{119}), + common.BytesToAddress([]byte{118}), + common.BytesToAddress([]byte{117}), + common.BytesToAddress([]byte{116}), + common.BytesToAddress([]byte{115}), + common.BytesToAddress([]byte{114}), + common.BytesToAddress([]byte{113}), + common.BytesToAddress([]byte{112}), + common.BytesToAddress([]byte{111}), + common.BytesToAddress([]byte{110}), + common.BytesToAddress([]byte{109}), + common.BytesToAddress([]byte{108}), + common.BytesToAddress([]byte{107}), + common.BytesToAddress([]byte{106}), + common.BytesToAddress([]byte{105}), + common.BytesToAddress([]byte{104}), + common.BytesToAddress([]byte{103}), + common.BytesToAddress([]byte{102}), + common.BytesToAddress([]byte{101}), + common.BytesToAddress([]byte{100}), } ) -/** +/* +* verifyHeadersTestCode represents the following smart contract code // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0 <0.9.0; contract VerifyHeaderTestContract { - constructor() {} - - function verify(bytes memory header1, bytes memory header2) public view returns (bool) { - bytes memory payload = abi.encodeWithSignature("validatingDoubleSignProof(bytes,bytes)", header1, header2); - uint payloadLength = payload.length; - address _smc = address(0x67); - uint[1] memory _output; - assembly { - let payloadStart := add(payload, 32) - if iszero(staticcall(0, _smc, payloadStart, payloadLength, _output, 0x20)) { - revert(0, 0) - } - } - return (_output[0] != 0); - } -} + constructor() {} + + function verify(bytes memory header1, bytes memory header2) public view returns (bool) { + bytes memory payload = abi.encodeWithSignature("validatingDoubleSignProof(bytes,bytes)", header1, header2); + uint payloadLength = payload.length; + address _smc = address(0x67); + uint[1] memory _output; + assembly { + let payloadStart := add(payload, 32) + if iszero(staticcall(0, _smc, payloadStart, payloadLength, _output, 0x20)) { + revert(0, 0) + } + } + return (_output[0] != 0); + } + } */ var ( verifyHeadersTestCode = "608060405234801561001057600080fd5b50610299806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f7e83aee14610030575b600080fd5b61004361003e36600461018b565b610057565b604051901515815260200160405180910390f35b600080838360405160240161006d929190610235565b60408051601f198184030181529190526020810180516001600160e01b031663580a316360e01b179052805190915060676100a66100ca565b602084016020828583866000fa6100bc57600080fd5b505115159695505050505050565b60405180602001604052806001906020820280368337509192915050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261010f57600080fd5b813567ffffffffffffffff8082111561012a5761012a6100e8565b604051601f8301601f19908116603f01168101908282118183101715610152576101526100e8565b8160405283815286602085880101111561016b57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806040838503121561019e57600080fd5b823567ffffffffffffffff808211156101b657600080fd5b6101c2868387016100fe565b935060208501359150808211156101d857600080fd5b506101e5858286016100fe565b9150509250929050565b6000815180845260005b81811015610215576020818501810151868301820152016101f9565b506000602082860101526020601f19601f83011685010191505092915050565b60408152600061024860408301856101ef565b828103602084015261025a81856101ef565b9594505050505056fea2646970667358221220e689890bbe17c2e97389470ed4baa21af25fd9cd6348d7511924615440d967d364736f6c63430008110033" verifyHeadersTestAbi = `[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"bytes","name":"header1","type":"bytes"},{"internalType":"bytes","name":"header2","type":"bytes"}],"name":"verify","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]` ) +var ( + addressesTest = []common.Address{ + common.BytesToAddress([]byte{100}), + common.BytesToAddress([]byte{101}), + common.BytesToAddress([]byte{102}), + common.BytesToAddress([]byte{103}), + common.BytesToAddress([]byte{104}), + common.BytesToAddress([]byte{105}), + common.BytesToAddress([]byte{106}), + common.BytesToAddress([]byte{107}), + common.BytesToAddress([]byte{108}), + common.BytesToAddress([]byte{109}), + common.BytesToAddress([]byte{110}), + common.BytesToAddress([]byte{111}), + common.BytesToAddress([]byte{112}), + common.BytesToAddress([]byte{113}), + common.BytesToAddress([]byte{114}), + common.BytesToAddress([]byte{115}), + common.BytesToAddress([]byte{116}), + common.BytesToAddress([]byte{117}), + common.BytesToAddress([]byte{118}), + common.BytesToAddress([]byte{119}), + common.BytesToAddress([]byte{120}), + } + weightsTest = []*big.Int{ + big.NewInt(1_000_000), + big.NewInt(2_000_000), + big.NewInt(3_000_000), + big.NewInt(4_000_000), + big.NewInt(5_000_000), + big.NewInt(6_000_000), + big.NewInt(7_000_000), + big.NewInt(8_000_000), + big.NewInt(9_000_000), + big.NewInt(10_000_000), + big.NewInt(11_000_000), + big.NewInt(12_000_000), + big.NewInt(13_000_000), + big.NewInt(14_000_000), + big.NewInt(15_000_000), + big.NewInt(16_000_000), + big.NewInt(17_000_000), + big.NewInt(18_000_000), + big.NewInt(19_000_000), + big.NewInt(20_000_000), + big.NewInt(22_000_000), + } +) + func TestSort(t *testing.T) { addrs := []common.Address{ common.BytesToAddress([]byte{102}), @@ -191,17 +310,19 @@ func TestSort(t *testing.T) { } } +// TestConsortiumValidatorSorting_Run sorts 21 validators successfully func TestConsortiumValidatorSorting_Run(t *testing.T) { var ( statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - limit = 21 ) smcAbi, err := abi.JSON(strings.NewReader(consortiumSortValidatorAbi)) if err != nil { t.Fatal(err) } - input, err := smcAbi.Pack(sortValidatorsMethod, big.NewInt(int64(limit))) + + input, err := smcAbi.Pack(sortValidatorsMethod, addressesTest, weightsTest) + if err != nil { t.Fatal(err) } @@ -215,18 +336,18 @@ func TestConsortiumValidatorSorting_Run(t *testing.T) { if err != nil { t.Fatal(err) } - println(common.Bytes2Hex(output)) + //println(common.Bytes2Hex(output)) res, err := smcAbi.Methods[sortValidatorsMethod].Outputs.Unpack(output) if err != nil { t.Fatal(err) } - sortedValidators := *abi.ConvertType(res[0], new([]common.Address)).(*[]common.Address) + sortedValidators := *abi.ConvertType(res[0], new([21]common.Address)).(*[21]common.Address) if len(expectedValidators) != len(sortedValidators) { - t.Fatal(fmt.Sprintf("expected len %d, got %v", limit, len(sortedValidators))) + t.Fatal(fmt.Sprintf("expected len %d, got %v", 21, len(sortedValidators))) } for i, addr := range sortedValidators { - println(addr.Hex()) + //println(addr.Hex()) if expectedValidators[i].Hex() != addr.Hex() { t.Fatal(fmt.Sprintf("mismatched addr at %d, expected:%s got:%s", i, expectedValidators[i].Hex(), addr.Hex())) } @@ -246,6 +367,7 @@ func TestConsortiumValidatorSorting_Run2(t *testing.T) { if err != nil { t.Fatal(err) } + evm, err := newEVM(caller, statedb) if err != nil { t.Fatal(err) @@ -273,7 +395,6 @@ func TestConsortiumValidatorSorting_Run2(t *testing.T) { t.Fatal(fmt.Sprintf("expected len 21, got %v", len(sortedValidators))) } for i, addr := range sortedValidators { - println(addr.Hex()) if expectedValidators[i].Hex() != addr.Hex() { t.Fatal(fmt.Sprintf("mismatched addr at %d, expected:%s got:%s", i, expectedValidators[i].Hex(), addr.Hex())) } @@ -473,7 +594,7 @@ func newEVM(caller common.Address, statedb StateDB) (*EVM, error) { }, chainConfig: params.TestChainConfig, StateDB: statedb, - chainRules: params.Rules{IsIstanbul: true}, + chainRules: params.Rules{IsIstanbul: true, IsEIP150: true}, } evm.interpreter = NewEVMInterpreter(evm, Config{NoBaseFee: true}) _, contract, _, err := evm.Create(AccountRef(caller), common.FromHex(testSortCode), math.MaxUint64/2, big0) From 397d0d6131a0440d76cd142a7eb3bdacf21bcae8 Mon Sep 17 00:00:00 2001 From: Linh Tran <110378492+linh-1@users.noreply.github.com> Date: Fri, 14 Oct 2022 13:17:23 +0700 Subject: [PATCH 49/52] fix(entrypoint): failed to decode keystore key (#142) --- docker/chainnode/entrypoint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/chainnode/entrypoint.sh b/docker/chainnode/entrypoint.sh index 1b9d335435..ef7e13543e 100755 --- a/docker/chainnode/entrypoint.sh +++ b/docker/chainnode/entrypoint.sh @@ -13,7 +13,7 @@ # constants datadir="/ronin/data" KEYSTORE_DIR="/ronin/keystore" -PASSWORD_FILE="$KEYSTORE_DIR/password" +PASSWORD_FILE="/ronin/password" # variables genesisPath="" From 8ceabe72c2a3d5b2fb18db6983c8e94d85889af3 Mon Sep 17 00:00:00 2001 From: minh-bq <97180373+minh-bq@users.noreply.github.com> Date: Fri, 14 Oct 2022 13:18:25 +0700 Subject: [PATCH 50/52] chore: add staking contract to chainconfig log (#144) --- params/config.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/params/config.go b/params/config.go index 88366690cf..9646456baf 100644 --- a/params/config.go +++ b/params/config.go @@ -459,7 +459,12 @@ func (c *ChainConfig) String() string { slashIndicatorSC = c.ConsortiumV2Contracts.SlashIndicator } - return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Odysseus: %v, Fenix: %v, Muir Glacier: %v, Berlin: %v, London: %v, Arrow Glacier: %v, Engine: %v, Blacklist Contract: %v, Fenix Validator Contract: %v, ConsortiumV2: %v, ConsortiumV2.RoninValidatorSet: %v, ConsortiumV2.SlashIndicator: %v}", + stakingContract := common.HexToAddress("") + if c.ConsortiumV2Contracts != nil { + stakingContract = c.ConsortiumV2Contracts.StakingContract + } + + return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Odysseus: %v, Fenix: %v, Muir Glacier: %v, Berlin: %v, London: %v, Arrow Glacier: %v, Engine: %v, Blacklist Contract: %v, Fenix Validator Contract: %v, ConsortiumV2: %v, ConsortiumV2.RoninValidatorSet: %v, ConsortiumV2.SlashIndicator: %v, ConsortiumV2.StakingContract: %v}", c.ChainID, c.HomesteadBlock, c.DAOForkBlock, @@ -483,6 +488,7 @@ func (c *ChainConfig) String() string { c.ConsortiumV2Block, roninValidatorSetSC.Hex(), slashIndicatorSC.Hex(), + stakingContract.Hex(), ) } From fea4017ee0b284aef963ffd3e651a97cfe7380c6 Mon Sep 17 00:00:00 2001 From: linh-1 Date: Wed, 19 Oct 2022 17:41:30 +0700 Subject: [PATCH 51/52] docs(README): update overview and contributions --- README.md | 103 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 58 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index ff1de0a9fe..70e9595ad9 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,15 @@ ## Go Ronin -Official Golang implementation of the Ronin protocol. +Official Golang execution layer implementation of the Ronin protocol. It is a fork of Go Ethereum - +[https://github.com/ethereum/go-ethereum](https://github.com/ethereum/go-ethereum) and EVM compatible. -Ronin is a Byzantine Fault Tolerant proof of authority (POA) network operated by validators. Carefully selected, trusted validators are predefined at the bootstrap of the network. Later, new validators can be added or old validators can be removed if the decision is approved by the majority of currently active validators. +Ronin consensus is using delegated proof of stake to enable complete decentralization as well as nodes' +freedom to join the network as validators. -In the future, Ronin consensus will be migrated to dPOS to enable complete decentralization as well as nodes' freedom to join the network as validators/miners. dPoS is a more democratic way of choosing who verifies the next block, allowing a more diverse group of people to participate in the process since it’s based on earned reputation as a lawful staker and not overall wealth. Additionally, because there are a limited number of validators, DPoS allows the network to reach consensus more quickly. - -Ronin starts its development based on go-ethereum fork. So you may see many toolings, binaries and also docs are based on Ethereum ones +Check out the [whitepaper]() for more information. [![Discord](https://img.shields.io/badge/discord-join%20chat-blue.svg)](https://discord.com/invite/pjgPrrZJyZ) -## Building the source - -Building `ronin` requires both a Go (version 1.17 or later) and a C compiler. You can install -them using your favourite package manager. Once the dependencies are installed, run - -```shell -make ronin -``` - -or, to build the full suite of utilities: - -```shell -make all -``` - ## Executables The go-ethereum project comes with several wrappers/executables found in the `cmd` @@ -48,6 +33,28 @@ Going through all the possible command line flags is out of scope here (please c but we've enumerated a few common parameter combos to get you up to speed quickly on how you can run your own `geth` instance. +### Requirements +The minimum recommended hardware specification for nodes connected to Mainnet is: +- CPU: Equivalent of 8 AWS vCPU +- RAM: 16GiB +- Storage: 1 TiB +- OS: Ubuntu 20.04 or macOS >= 12 +- Network: Reliable IPv4 or IPv6 network connection, with an open public port + +### Building the source +Building `ronin` requires both a Go (version 1.17 or later) and a C compiler. You can install +them using your favourite package manager. Once the dependencies are installed, run + +```shell +make ronin +``` + +or, to build the full suite of utilities: + +```shell +make all +``` + ### Full node on the main Ronin network ```shell @@ -116,31 +123,37 @@ Ethereum nodes with exposed APIs! Further, all browser tabs can access locally running web servers, so malicious web pages could try to subvert locally available APIs!** -## Contribution - -Thank you for considering to help out with the source code! We welcome contributions -from anyone on the internet, and are grateful for even the smallest of fixes! - -If you'd like to contribute to go-ethereum, please fork, fix, commit and send a pull request -for the maintainers to review and merge into the main code base. If you wish to submit -more complex changes though, please check up with the core devs first on [our Discord Server](https://discord.com/invite/pjgPrrZJyZ) -to ensure those changes are in line with the general philosophy of the project and/or get -some early feedback which can make both your efforts much lighter as well as our review -and merge procedures quick and simple. - -Please make sure your contributions adhere to our coding guidelines: - - * Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) - guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)). - * Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) - guidelines. - * Pull requests need to be based on and opened against the `master` branch. - * Commit messages should be prefixed with the package(s) they modify. - * E.g. "eth, rpc: make trace configs optional" - -Please see the [Developers' Guide](https://geth.ethereum.org/docs/developers/devguide) -for more details on configuring your environment, managing project dependencies, and -testing procedures. +## How to contribute + +### Contribution guidelines +- Quality: Code in the Ronin project should meet the style guidelines, with sufficient test-cases, descriptive commit + messages, evidence that the contribution does not break any compatibility commitments or cause adverse feature + interactions, and evidence of high-quality peer-review. +- Size: The Ronin project's culture is one of small pull-requests, regularly submitted. The larger a pull-request, + the more likely it is that you will be asked to resubmit as a series of self-contained and individually reviewable + smaller PRs. +- Maintainability: If the feature will require ongoing maintenance (eg support for a particular branch of database), + we nay ask you to accept responsibility for maintaining this feature +- Commit message: Commit messages of Ronin project follows [https://www.conventionalcommits.org/en/v1.0.0/](https://www.conventionalcommits.org/en/v1.0.0/) + +### Submit an issue +- Create a new issue +- Comment on the issue (if you'd like to be assigned to it) - that way our team can assign the issue to you +- If you do not have a specific contribution in mind, you can also browse the issues labelled as `help wanted` +- Issues that additionally have the `good first issue` label are considered ideal for first-timers + +### Submit your PR +- After your changes are committed to your GitHub fork, submit a pull request (PR) to the `master` branch of the + axieinfinity/ronin repo +- In your PR description, reference the issue it resolves (see [linking a pull request to an issue using a keyword](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword)) + - ex: `[FIXES #123] feat: update out of date content` + +### Wait for review +- The team reviews every PR +- Acceptable PRs will be approved & merged into the `master` branch + +### Release +- You can [view the history of release](https://github.com/axieinfinity/ronin/releases), which include PR highlights ## License From 832c7428fd5dda5c0671f4674c3835c43d35567c Mon Sep 17 00:00:00 2001 From: "linh.tran" Date: Mon, 14 Nov 2022 13:40:40 +0700 Subject: [PATCH 52/52] chore: update README content --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 70e9595ad9..5969911816 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,8 @@ Official Golang execution layer implementation of the Ronin protocol. It is a fork of Go Ethereum - [https://github.com/ethereum/go-ethereum](https://github.com/ethereum/go-ethereum) and EVM compatible. -Ronin consensus is using delegated proof of stake to enable complete decentralization as well as nodes' -freedom to join the network as validators. +Ronin consensus use Proof of Staked Authority, a combination of dPoS and PoA, to increase the level of +decentralization and allows the token holders to join the network as validators Check out the [whitepaper]() for more information.