diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index be0f92fa6c..f8f736ae6b 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1020,7 +1020,7 @@ var ( MaxCurVoteAmountPerBlock = &cli.IntFlag{ Name: "votepool.maxcurvoteperblock", Usage: "The maximum finality vote per current block", - Value: 22, + Value: 64, Category: flags.FastFinalityCategory, } diff --git a/consensus/consortium/v2/consortium.go b/consensus/consortium/v2/consortium.go index 12ff23c94a..e35499c1ea 100644 --- a/consensus/consortium/v2/consortium.go +++ b/consensus/consortium/v2/consortium.go @@ -116,6 +116,7 @@ type Consortium struct { votePool consensus.VotePool // This is used in unit test only + isTest bool testTrippEffective bool testTrippPeriod bool } @@ -270,7 +271,7 @@ func (c *Consortium) VerifyVote(chain consensus.ChainHeaderReader, vote *types.V // verifyFinalitySignatures verifies the finality signatures in the block header func (c *Consortium) verifyFinalitySignatures( chain consensus.ChainHeaderReader, - finalityVotedValidators finality.FinalityVoteBitSet, + finalityVotedValidators finality.BitSet, finalitySignatures blsCommon.Signature, header *types.Header, parents []*types.Header, @@ -354,6 +355,44 @@ func (c *Consortium) VerifyHeaderAndParents(chain consensus.ChainHeaderReader, h return c.verifyCascadingFields(chain, header, parents) } +func (c *Consortium) verifyValidatorFieldsInExtraData( + chain consensus.ChainHeaderReader, + extraData *finality.HeaderExtraData, + header *types.Header, +) error { + isEpoch := header.Number.Uint64()%c.config.EpochV2 == 0 || c.chainConfig.IsOnConsortiumV2(header.Number) + if !isEpoch && (len(extraData.CheckpointValidators) != 0 || len(extraData.BlockProducers) != 0) || extraData.BlockProducersBitSet != 0 { + return consortiumCommon.ErrExtraValidators + } + + if c.IsTrippEffective(chain, header) { + if c.chainConfig.IsAaron(header.Number) { + if isEpoch && (extraData.BlockProducersBitSet == 0 || len(extraData.BlockProducers) != 0) { + return consortiumCommon.ErrExtraValidators + } + } else if isEpoch && (extraData.BlockProducersBitSet != 0 || len(extraData.BlockProducers) == 0) { + return consortiumCommon.ErrExtraValidators + } + if c.IsPeriodBlock(chain, header) { + if len(extraData.CheckpointValidators) == 0 { + return consortiumCommon.ErrExtraValidators + } + } else { + if len(extraData.CheckpointValidators) != 0 { + return consortiumCommon.ErrExtraValidators + } + } + } else { + if isEpoch && len(extraData.CheckpointValidators) == 0 { + return consortiumCommon.ErrExtraValidators + } + if len(extraData.BlockProducers) != 0 || extraData.BlockProducersBitSet != 0 { + return consortiumCommon.ErrExtraValidators + } + } + return nil +} + // 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 @@ -378,33 +417,14 @@ func (c *Consortium) verifyCascadingFields(chain consensus.ChainHeaderReader, he // Check extra data isShillin := c.chainConfig.IsShillin(header.Number) - isTrippEffective := c.IsTrippEffective(chain, header) extraData, err := finality.DecodeExtraV2(header.Extra, c.chainConfig, header.Number) if err != nil { return err } - // Check extra data - isEpoch := number%c.config.EpochV2 == 0 || c.chainConfig.IsOnConsortiumV2(header.Number) - - if !isEpoch && (len(extraData.CheckpointValidators) != 0 || len(extraData.BlockProducers) != 0) { - return consortiumCommon.ErrExtraValidators - } - - if isTrippEffective { - if isEpoch && len(extraData.BlockProducers) == 0 { - return consortiumCommon.ErrExtraValidators - } - if c.IsPeriodBlock(chain, header) && len(extraData.CheckpointValidators) == 0 { - return consortiumCommon.ErrExtraValidators - } - } else { - if isEpoch && len(extraData.CheckpointValidators) == 0 { - return consortiumCommon.ErrExtraValidators - } - if len(extraData.BlockProducers) != 0 { - return consortiumCommon.ErrExtraValidators - } + err = c.verifyValidatorFieldsInExtraData(chain, extraData, header) + if err != nil { + return err } if isShillin && extraData.HasFinalityVote == 1 { @@ -723,7 +743,10 @@ func (c *Consortium) getCheckpointValidatorsFromContract( var checkpointValidators []finality.ValidatorWithBlsPub if c.IsTrippEffective(chain, header) { - sort.Sort(validatorsAscending(blockProducers)) + isAaron := c.chainConfig.IsAaron(header.Number) + if !isAaron { + sort.Sort(validatorsAscending(blockProducers)) + } if !c.IsPeriodBlock(chain, header) { return nil, blockProducers, nil } @@ -734,6 +757,14 @@ func (c *Consortium) getCheckpointValidatorsFromContract( if len(validatorCandidates) > MaxValidatorCandidates { validatorCandidates = validatorCandidates[:MaxValidatorCandidates] } + + // After Aaron, bit set is used, it is necessary to keep + // the validator candidate list in a ascending order, which + // enable block producer list to be consistent after reconstruction. + if isAaron { + sort.Sort(validatorsAscending(validatorCandidates)) + } + stakedAmounts, err := c.contract.GetStakedAmount(parentHash, parentBlockNumber, validatorCandidates) if err != nil { return nil, nil, err @@ -812,20 +843,39 @@ func (c *Consortium) Prepare(chain consensus.ChainHeaderReader, header *types.He var extraData finality.HeaderExtraData if number%c.config.EpochV2 == 0 || c.chainConfig.IsOnConsortiumV2(big.NewInt(int64(number))) { - checkpointValidator, blockProducers, err := c.getCheckpointValidatorsFromContract(chain, header) + checkpointValidators, blockProducers, err := c.getCheckpointValidatorsFromContract(chain, header) if err != nil { return err } - // After Tripp, validator candidates are read only once at - // the start of new period, whereas block producer address is read - // at the start of every epoch. + // After Tripp, validator candidate list is read only once at + // the start of new period and does not change over the whole + // period; whereas block producer list is changed and read at + // the start of every new epoch. if c.IsTrippEffective(chain, header) { + // latestValidatorCandidates is the latest validator candidate list at the + // current epoch, which is used to calculate block producer bit set later on. + var latestValidatorCandidates []finality.ValidatorWithBlsPub + if c.IsPeriodBlock(chain, header) { - extraData.CheckpointValidators = checkpointValidator + extraData.CheckpointValidators = checkpointValidators + latestValidatorCandidates = checkpointValidators + } else { + // Except period block, checkpoint validator list get from contract + // is nil at other epoch blocks. From the fact that validator candidate list + // does not change over the whole period, it's possible to get the latest + // validator candidate set from the snapshot. + latestValidatorCandidates = snap.ValidatorsWithBlsPub + } + // After Aaron, to reduce memory to store block producer list + // in header, block producer bit set is constructed to store the + // indices of block producer in validator candidate lists. + if c.chainConfig.IsAaron(header.Number) { + extraData.BlockProducersBitSet = encodeValidatorBitSet(latestValidatorCandidates, blockProducers) + } else { + extraData.BlockProducers = blockProducers } - extraData.BlockProducers = blockProducers } else { - extraData.CheckpointValidators = checkpointValidator + extraData.CheckpointValidators = checkpointValidators } } @@ -941,7 +991,7 @@ func (c *Consortium) processSystemTransactions(chain consensus.ChainHeaderReader } func (c *Consortium) upgradeRoninTrustedOrg(blockNumber *big.Int, state *state.StateDB) { - // The upgrade only happens in 1 block: Miko hardfork block + // The upgrade only happens once at Miko hardfork block if c.chainConfig.MikoBlock != nil && c.chainConfig.MikoBlock.Cmp(blockNumber) == 0 { state.SetState( c.chainConfig.RoninTrustedOrgUpgrade.ProxyAddress, @@ -951,6 +1001,21 @@ func (c *Consortium) upgradeRoninTrustedOrg(blockNumber *big.Int, state *state.S } } +func (c *Consortium) upgradeTransparentProxyCode(blockNumber *big.Int, statedb *state.StateDB) { + // The transparent proxy code upgrade only happens once at Aaron hardfork block + if c.chainConfig.AaronBlock != nil && c.chainConfig.AaronBlock.Cmp(blockNumber) == 0 { + code := c.chainConfig.TransparentProxyCodeUpgrade.Code + statedb.SetCode( + c.chainConfig.TransparentProxyCodeUpgrade.AxieAddress, + code, + ) + statedb.SetCode( + c.chainConfig.TransparentProxyCodeUpgrade.LandAddress, + code, + ) + } +} + // 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 @@ -977,6 +1042,10 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H SignTxFn: signTxFn, EthAPI: c.ethAPI, } + snap, err := c.snapshot(chain, header.Number.Uint64()-1, header.ParentHash, nil) + if err != nil { + return err + } // 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. @@ -993,13 +1062,27 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H // If isTripp and new period, read all validator candidates and // their amounts, check with stored data in header if c.IsTrippEffective(chain, header) { - if len(blockProducers) != len(extraData.BlockProducers) { - return errMismatchingValidators - } - for i := range blockProducers { - if blockProducers[i] != extraData.BlockProducers[i] { + if c.chainConfig.IsAaron(header.Number) { + if !c.IsPeriodBlock(chain, header) { + // Except period block, checkpoint validator list get from contract + // is nil at other epoch blocks. From the fact that validator candidate list + // does not change over the whole period, it's possible to get the latest + // validator candidate set from the snapshot. + checkpointValidators = snap.ValidatorsWithBlsPub + } + bitSet := encodeValidatorBitSet(checkpointValidators, blockProducers) + if bitSet != extraData.BlockProducersBitSet { + return errMismatchingValidators + } + } else { + if len(blockProducers) != len(extraData.BlockProducers) { return errMismatchingValidators } + for i := range blockProducers { + if blockProducers[i] != extraData.BlockProducers[i] { + return errMismatchingValidators + } + } } if c.IsPeriodBlock(chain, header) { if len(checkpointValidators) != len(extraData.CheckpointValidators) { @@ -1041,6 +1124,7 @@ func (c *Consortium) Finalize(chain consensus.ChainHeaderReader, header *types.H return err } c.upgradeRoninTrustedOrg(header.Number, state) + c.upgradeTransparentProxyCode(header.Number, state) if len(*transactOpts.EVMContext.InternalTransactions) > 0 { *internalTxs = append(*internalTxs, *transactOpts.EVMContext.InternalTransactions...) } @@ -1087,7 +1171,7 @@ func (c *Consortium) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head return nil, nil, err } c.upgradeRoninTrustedOrg(header.Number, state) - + c.upgradeTransparentProxyCode(header.Number, state) // 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") @@ -1357,7 +1441,7 @@ func (c *Consortium) assembleFinalityVote(chain consensus.ChainHeaderReader, hea if c.chainConfig.IsShillin(header.Number) { var ( signatures []blsCommon.Signature - finalityVotedValidators finality.FinalityVoteBitSet + finalityVotedValidators finality.BitSet finalityThreshold int accumulatedVoteWeight int ) @@ -1610,6 +1694,27 @@ func encodeSigHeader(w io.Writer, header *types.Header, chainId *big.Int) { } } +func encodeValidatorBitSet(validatorCandidates []finality.ValidatorWithBlsPub, blockProducers []common.Address) finality.BitSet { + var bitSet finality.BitSet + for _, validator := range blockProducers { + for idx, candidate := range validatorCandidates { + if validator == candidate.Address { + bitSet.SetBit(idx) + } + } + } + return bitSet +} + +func decodeValidatorBitSet(bitSet finality.BitSet, validatorCandidates []finality.ValidatorWithBlsPub) []common.Address { + indices := bitSet.Indices() + blockProducers := make([]common.Address, len(indices)) + for i, idx := range indices { + blockProducers[i] = validatorCandidates[idx].Address + } + return blockProducers +} + // getLastCheckpointHeader returns the last checkpoint header, this function is used as a fallback when we cannot // get the snapshot to query the period number func (c *Consortium) getLastCheckpointHeader(chain consensus.ChainHeaderReader, currentHeader *types.Header) *types.Header { @@ -1634,10 +1739,9 @@ func (c *Consortium) getLastCheckpointHeader(chain consensus.ChainHeaderReader, // IsPeriodBlock returns indicator whether a block is a period checkpoint block or not, // which is the first checkpoint block (block % EpochV2 == 0) after 00:00 UTC everyday. func (c *Consortium) IsPeriodBlock(chain consensus.ChainHeaderReader, header *types.Header) bool { - if c.testTrippPeriod { - return true + if c.isTest { + return c.testTrippPeriod } - number := header.Number.Uint64() if number%c.config.EpochV2 != 0 || !chain.Config().IsTripp(header.Number) { return false @@ -1661,6 +1765,9 @@ func (c *Consortium) IsPeriodBlock(chain consensus.ChainHeaderReader, header *ty // which is the first period that is greater than Tripp period, calculated by formula: // period := timestamp / dayInSeconds. func (c *Consortium) IsTrippEffective(chain consensus.ChainHeaderReader, header *types.Header) bool { + if c.isTest { + return c.testTrippEffective + } if c.chainConfig.IsTripp(header.Number) { if c.testTrippEffective { return true diff --git a/consensus/consortium/v2/consortium_test.go b/consensus/consortium/v2/consortium_test.go index 6ad58d0936..66981b01e4 100644 --- a/consensus/consortium/v2/consortium_test.go +++ b/consensus/consortium/v2/consortium_test.go @@ -5,9 +5,12 @@ import ( "crypto/ecdsa" "crypto/rand" "encoding/binary" + "encoding/json" "errors" "io" "math/big" + mrand "math/rand" + "sort" "testing" "time" @@ -534,20 +537,20 @@ func TestExtraDataDecode(t *testing.T) { func mockExtraData(nVal int, bits uint32) *finality.HeaderExtraData { var ( - finalityVotedValidators finality.FinalityVoteBitSet + finalityVotedValidators finality.BitSet aggregatedFinalityVotes blsCommon.Signature checkpointValidators []finality.ValidatorWithBlsPub seal = make([]byte, finality.ExtraSeal) ret = &finality.HeaderExtraData{} ) - bits = bits % 32 - for i := 0; i < 5; i++ { + bits = bits % 64 + for i := 0; i < 6; i++ { if bits&(1<= finalityVoteBitSetByteLength*8 { return 0 } @@ -159,12 +159,12 @@ func (bitSet *FinalityVoteBitSet) GetBit(index int) int { return int((uint64(*bitSet) >> index) & 1) } -func (bitSet *FinalityVoteBitSet) SetBit(index int) { +func (bitSet *BitSet) SetBit(index int) { if index >= finalityVoteBitSetByteLength*8 { return } - *bitSet = FinalityVoteBitSet(uint64(*bitSet) | (1 << index)) + *bitSet = BitSet(uint64(*bitSet) | (1 << index)) } // HeaderExtraData represents the information in the extra data of header, @@ -172,10 +172,11 @@ func (bitSet *FinalityVoteBitSet) SetBit(index int) { type HeaderExtraData struct { Vanity [ExtraVanity]byte // unused in Consortium, filled with zero HasFinalityVote uint8 // determine if the header extra has the finality vote - FinalityVotedValidators FinalityVoteBitSet // the bit set of validators that vote for finality + FinalityVotedValidators BitSet // the bit set of validators that vote for finality AggregatedFinalityVotes blsCommon.Signature // aggregated BLS signatures for finality vote CheckpointValidators []ValidatorWithBlsPub // validator addresses and BLS public key updated at period block BlockProducers []common.Address // block producer addresses updated at epoch block + BlockProducersBitSet BitSet // the bit set of validators that can produce blocks Seal [ExtraSeal]byte // the sealing block signature } @@ -232,7 +233,7 @@ func DecodeExtra(rawBytes []byte, isShillin bool) (*HeaderExtraData, error) { if rawBytesLength-currentPosition < finalityVoteBitSetByteLength { return nil, ErrMissingFinalityVoteBitSet } - extraData.FinalityVotedValidators = FinalityVoteBitSet( + extraData.FinalityVotedValidators = BitSet( binary.LittleEndian.Uint64(rawBytes[currentPosition : currentPosition+finalityVoteBitSetByteLength]), ) currentPosition += finalityVoteBitSetByteLength @@ -274,10 +275,11 @@ func DecodeExtra(rawBytes []byte, isShillin bool) (*HeaderExtraData, error) { // by AggregatedFinalityVotes and FinalityVotedValidators. On the other hand, seal is // appended manually, enabling encodeSigHeader easily to exclude Seal before signing process type extraDataRLP struct { - FinalityVotedValidators FinalityVoteBitSet + FinalityVotedValidators BitSet AggregatedFinalityVotes []byte CheckpointValidators []validatorWithBlsPubRLP BlockProducers []common.Address + BlockProducersBitSet BitSet `rlp:"optional"` } type validatorWithBlsPubRLP struct { @@ -315,6 +317,7 @@ func (extraData *HeaderExtraData) EncodeRLP() ([]byte, error) { } ext.CheckpointValidators = cp ext.BlockProducers = extraData.BlockProducers + ext.BlockProducersBitSet = extraData.BlockProducersBitSet enc, err := rlp.EncodeToBytes(ext) if err != nil { @@ -354,6 +357,7 @@ func DecodeExtraRLP(enc []byte) (*HeaderExtraData, error) { } ret.CheckpointValidators = cp ret.BlockProducers = dec.BlockProducers + ret.BlockProducersBitSet = dec.BlockProducersBitSet if len(dec.AggregatedFinalityVotes) != 0 && len(dec.FinalityVotedValidators.Indices()) != 0 { ret.HasFinalityVote = 1 diff --git a/consensus/consortium/v2/finality/consortium_header_test.go b/consensus/consortium/v2/finality/consortium_header_test.go index 8996737596..92f81205cd 100644 --- a/consensus/consortium/v2/finality/consortium_header_test.go +++ b/consensus/consortium/v2/finality/consortium_header_test.go @@ -10,7 +10,7 @@ import ( ) func TestFinalityVoteBitSet(t *testing.T) { - var bitSet FinalityVoteBitSet + var bitSet BitSet bitSet.SetBit(0) bitSet.SetBit(40) diff --git a/consensus/consortium/v2/snapshot.go b/consensus/consortium/v2/snapshot.go index 209bc0dcde..c903379dc1 100644 --- a/consensus/consortium/v2/snapshot.go +++ b/consensus/consortium/v2/snapshot.go @@ -273,6 +273,7 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea } isTripp := chain.Config().IsTripp(header.Number) + isAaron := s.chainConfig.IsAaron(header.Number) if isTripp && number%s.config.EpochV2 == 0 && header.Time/dayInSeconds > snap.CurrentPeriod { snap.CurrentPeriod = header.Time / dayInSeconds } @@ -302,7 +303,9 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea var newLimit int // After Tripp, list of block producers is retrieved from the // field BlockProducer, instead of field CheckpointValidators. - if isTripp && len(extraData.BlockProducers) != 0 { + if isAaron && extraData.BlockProducersBitSet != 0 { + newLimit = len(extraData.BlockProducersBitSet.Indices())/2 + 1 + } else if isTripp && len(extraData.BlockProducers) != 0 { newLimit = len(extraData.BlockProducers)/2 + 1 } else { newLimit = len(extraData.CheckpointValidators)/2 + 1 @@ -313,7 +316,15 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea } } - if isTripp && len(extraData.BlockProducers) != 0 { + // After Aaron, block producer list in snapshot is + // reconstructed from bit set and validator candidate list. + if isAaron && extraData.BlockProducersBitSet != 0 { + if len(extraData.CheckpointValidators) != 0 { + snap.ValidatorsWithBlsPub = extraData.CheckpointValidators + } + snap.BlockProducers = decodeValidatorBitSet(extraData.BlockProducersBitSet, snap.ValidatorsWithBlsPub) + snap.Validators = nil + } else if isTripp && len(extraData.BlockProducers) != 0 { // After Tripp is effective, the checkpoint validators in header's extra data // is set only at the period block, not at all checkpoint blocks anymore. So // only update snapshot's validator with bls public key when checkpoint diff --git a/core/vote/vote_pool.go b/core/vote/vote_pool.go index 03de97c1bc..1d7a0b5da1 100644 --- a/core/vote/vote_pool.go +++ b/core/vote/vote_pool.go @@ -15,7 +15,7 @@ import ( ) const ( - maxFutureVoteAmountPerBlock = 50 + maxFutureVoteAmountPerBlock = 64 maxFutureVotePerPeer = 25 voteBufferForPut = 256 diff --git a/genesis/testnet.json b/genesis/testnet.json index 42f3a80d64..679ae60ab1 100644 --- a/genesis/testnet.json +++ b/genesis/testnet.json @@ -36,10 +36,16 @@ "londonBlock": 27580600, "trippBlock": 27580600, "trippPeriod": 19866, + "aaronBlock": 28174200, "whiteListDeployerContractV2Address": "0x50a7e07Aa75eB9C04281713224f50403cA79851F", "roninTrustedOrgUpgrade": { "proxyAddress": "0x7507dc433a98E1fE105d69f19f3B40E4315A4F32", "implementationAddress": "0x6A51C2B073a6daDBeCAC1A420AFcA7788C81612f" + }, + "transparentProxyCodeUpgrade": { + "axieAddress": "0xcaCA1c072D26E46686d932686015207FbE08FdB8", + "landAddress": "0x70bd60F625F6Dd082aE1f59b80DC78CfA8B47F18", + "code": "0x60806040523661001357610011610017565b005b6100115b61001f6102a1565b73ffffffffffffffffffffffffffffffffffffffff1633036102975760607fffffffff00000000000000000000000000000000000000000000000000000000600035167fc9a6301a000000000000000000000000000000000000000000000000000000008101610098576100916102e1565b915061028f565b7fb0e10d7a000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216016100e957610091610338565b7f70d7c690000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000082160161013a5761009161037e565b7f07ae5bc0000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000082160161018b576100916103af565b7fa39f25e5000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216016101dc576100916103fc565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b815160208301f35b61029f610410565b565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b60606102eb610420565b60006102fa36600481846108d7565b810190610307919061092a565b90506103248160405180602001604052806000815250600061042b565b505060408051602081019091526000815290565b606060008061034a36600481846108d7565b8101906103579190610974565b915091506103678282600161042b565b604051806020016040528060008152509250505090565b6060610388610420565b600061039736600481846108d7565b8101906103a4919061092a565b905061032481610457565b60606103b9610420565b60006103c36102a1565b6040805173ffffffffffffffffffffffffffffffffffffffff831660208201529192500160405160208183030381529060405291505090565b6060610406610420565b60006103c36104bb565b61029f61041b6104bb565b6104ca565b341561029f57600080fd5b610434836104ee565b6000825111806104415750805b1561045257610450838361053b565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104806102a1565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a16104b881610567565b50565b60006104c5610673565b905090565b3660008037600080366000845af43d6000803e8080156104e9573d6000f35b3d6000fd5b6104f78161069b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606105608383604051806060016040528060278152602001610b0d60279139610766565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811661060a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610286565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6102c5565b73ffffffffffffffffffffffffffffffffffffffff81163b61073f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608401610286565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61062d565b60606000808573ffffffffffffffffffffffffffffffffffffffff16856040516107909190610a9f565b600060405180830381855af49150503d80600081146107cb576040519150601f19603f3d011682016040523d82523d6000602084013e6107d0565b606091505b50915091506107e1868383876107eb565b9695505050505050565b6060831561088157825160000361087a5773ffffffffffffffffffffffffffffffffffffffff85163b61087a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610286565b508161088b565b61088b8383610893565b949350505050565b8151156108a35781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102869190610abb565b600080858511156108e757600080fd5b838611156108f457600080fd5b5050820193919092039150565b803573ffffffffffffffffffffffffffffffffffffffff8116811461092557600080fd5b919050565b60006020828403121561093c57600080fd5b61056082610901565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806040838503121561098757600080fd5b61099083610901565b9150602083013567ffffffffffffffff8111156109ac57600080fd5b8301601f810185136109bd57600080fd5b803567ffffffffffffffff8111156109d7576109d7610945565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8501160116810181811067ffffffffffffffff82111715610a4357610a43610945565b604052818152828201602001871015610a5b57600080fd5b816020840160208301376000602083830101528093505050509250929050565b60005b83811015610a96578181015183820152602001610a7e565b50506000910152565b60008251610ab1818460208701610a7b565b9190910192915050565b6020815260008251806020840152610ada816040850160208701610a7b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220301172db114fe6fe4ccca8436137dc0e221398901bf5ca28b3dc1915e56ed0b664736f6c634300081a0033" } }, "alloc": { diff --git a/params/config.go b/params/config.go index 2984d880fe..3871bde9a8 100644 --- a/params/config.go +++ b/params/config.go @@ -23,6 +23,7 @@ import ( "reflect" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "golang.org/x/crypto/sha3" ) @@ -289,6 +290,7 @@ var ( }, // TODO: fill this TrippBlock: common.Big0, + AaronBlock: common.Big0, } RoninTestnetBlacklistContract = common.HexToAddress("0xF53EED5210c9cF308abFe66bA7CF14884c95A8aC") @@ -338,8 +340,11 @@ var ( ProxyAddress: common.HexToAddress("0x7507dc433a98E1fE105d69f19f3B40E4315A4F32"), ImplementationAddress: common.HexToAddress("0x6A51C2B073a6daDBeCAC1A420AFcA7788C81612f"), }, - // TODO: fill this - TrippBlock: common.Big0, + LondonBlock: big.NewInt(27580600), + BerlinBlock: big.NewInt(27580600), + TrippBlock: big.NewInt(27580600), + TrippPeriod: big.NewInt(19866), + AaronBlock: big.NewInt(28174200), } // GoerliTrustedCheckpoint contains the light client trusted checkpoint for the Görli test network. @@ -561,6 +566,7 @@ type ChainConfig struct { MikoBlock *big.Int `json:"mikoBlock,omitempty"` // Miko switch block (nil = no fork, 0 = already on activated) TrippBlock *big.Int `json:"trippBlock,omitempty"` // Tripp switch block (nil = no fork, 0 = already on activated) TrippPeriod *big.Int `json:"trippPeriod,omitempty"` // The period number at Tripp fork block. + AaronBlock *big.Int `json:"aaronBlock,omitempty"` // Aaron 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) @@ -570,11 +576,12 @@ 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"` - ConsortiumV2Contracts *ConsortiumV2Contracts `json:"consortiumV2Contracts"` - RoninTrustedOrgUpgrade *ContractUpgrade `json:"roninTrustedOrgUpgrade"` + Ethash *EthashConfig `json:"ethash,omitempty"` + Clique *CliqueConfig `json:"clique,omitempty"` + Consortium *ConsortiumConfig `json:"consortium,omitempty"` + ConsortiumV2Contracts *ConsortiumV2Contracts `json:"consortiumV2Contracts"` + RoninTrustedOrgUpgrade *ContractUpgrade `json:"roninTrustedOrgUpgrade"` + TransparentProxyCodeUpgrade *ContractCodeUpgrade `json:"transparentProxyCodeUpgrade"` } type ContractUpgrade struct { @@ -582,6 +589,12 @@ type ContractUpgrade struct { ImplementationAddress common.Address `json:"implementationAddress"` } +type ContractCodeUpgrade struct { + AxieAddress common.Address `json:"axieAddress"` + LandAddress common.Address `json:"landAddress"` + Code hexutil.Bytes `json:"code"` +} + // EthashConfig is the consensus engine configs for proof-of-work based sealing. type EthashConfig struct{} @@ -674,12 +687,12 @@ func (c *ChainConfig) String() string { whiteListDeployerContractV2Address = *c.WhiteListDeployerContractV2Address } - chainConfigFmt := "{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v " - chainConfigFmt += "Petersburg: %v Istanbul: %v, Odysseus: %v, Fenix: %v, Muir Glacier: %v, Berlin: %v, London: %v, Arrow Glacier: %v, " + chainConfigFmt := "{ChainID: %v, Homestead: %v, DAO: %v, DAOSupport: %v, EIP150: %v, EIP155: %v, EIP158: %v, Byzantium: %v, Constantinople: %v, " + chainConfigFmt += "Petersburg: %v, Istanbul: %v, Odysseus: %v, Fenix: %v, Muir Glacier: %v, Berlin: %v, London: %v, Arrow Glacier: %v, " chainConfigFmt += "Engine: %v, Blacklist Contract: %v, Fenix Validator Contract: %v, ConsortiumV2: %v, ConsortiumV2.RoninValidatorSet: %v, " chainConfigFmt += "ConsortiumV2.SlashIndicator: %v, ConsortiumV2.StakingContract: %v, Puffy: %v, Buba: %v, Olek: %v, Shillin: %v, Antenna: %v, " - chainConfigFmt += "ConsortiumV2.ProfileContract: %v, ConsortiumV2.FinalityTracking: %v, whiteListDeployerContractV2Address: %v, Miko: %v, Tripp: %v," - chainConfigFmt += "TrippPeriod: %v}" + chainConfigFmt += "ConsortiumV2.ProfileContract: %v, ConsortiumV2.FinalityTracking: %v, whiteListDeployerContractV2Address: %v, Miko: %v, Tripp: %v, " + chainConfigFmt += "TrippPeriod: %v, Aaron: %v}" return fmt.Sprintf(chainConfigFmt, c.ChainID, @@ -717,6 +730,7 @@ func (c *ChainConfig) String() string { c.MikoBlock, c.TrippBlock, c.TrippPeriod, + c.AaronBlock, ) } @@ -850,6 +864,11 @@ func (c *ChainConfig) IsTripp(num *big.Int) bool { return isForked(c.TrippBlock, num) } +// IsAaron returns whether the num is equals to or larger than the aaron fork block. +func (c *ChainConfig) IsAaron(num *big.Int) bool { + return isForked(c.AaronBlock, num) +} + // CheckCompatible checks whether scheduled fork transitions have been imported // with a mismatching chain configuration. func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64) *ConfigCompatError { @@ -993,6 +1012,9 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *Confi if isForkIncompatible(c.TrippBlock, newcfg.TrippBlock, head) { return newCompatError("Tripp fork block", c.TrippBlock, newcfg.TrippBlock) } + if isForkIncompatible(c.AaronBlock, newcfg.AaronBlock, head) { + return newCompatError("Aaron fork block", c.AaronBlock, newcfg.AaronBlock) + } return nil } @@ -1062,7 +1084,7 @@ type Rules struct { IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool IsBerlin, IsLondon bool IsOdysseusFork, IsFenix, IsConsortiumV2, IsAntenna bool - IsMiko bool + IsMiko, IsTripp, IsAaron bool } // Rules ensures c's ChainID is not nil. @@ -1088,5 +1110,7 @@ func (c *ChainConfig) Rules(num *big.Int) Rules { IsConsortiumV2: c.IsConsortiumV2(num), IsAntenna: c.IsAntenna(num), IsMiko: c.IsMiko(num), + IsTripp: c.IsTripp(num), + IsAaron: c.IsAaron(num), } } diff --git a/params/version.go b/params/version.go index ba1e159971..ee282f351b 100644 --- a/params/version.go +++ b/params/version.go @@ -23,7 +23,7 @@ import ( const ( VersionMajor = 2 // Major version component of the current release VersionMinor = 8 // Minor version component of the current release - VersionPatch = 0 // Patch version component of the current release + VersionPatch = 1 // Patch version component of the current release VersionMeta = "" // Version metadata to append to the version string )