diff --git a/cmd/puppeth/wizard_genesis.go b/cmd/puppeth/wizard_genesis.go index d882f84b4e60e38466b9c5acbc6eb8f58d337fd8..5973a8cebcd833bce50bfeb5b7c33e655d8c391c 100644 --- a/cmd/puppeth/wizard_genesis.go +++ b/cmd/puppeth/wizard_genesis.go @@ -108,9 +108,10 @@ func (w *wizard) makeGenesis() { genesis.Difficulty = big.NewInt(1) genesis.GasLimit = 10000000 genesis.Config.Bor = ¶ms.BorConfig{ - Period: 1, - ProducerDelay: 5, - Epoch: 60, + Period: 1, + ProducerDelay: 5, + Sprint: 60, + ValidatorContract: "0x0000000000000000000000000000000000001000", } // We also need the initial list of signers diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index 800de192a7e620aac228e888f5c770ab94c026c1..2c2fcf020fcd46ed38a1b13487853419962c2a43 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -8,6 +8,7 @@ import ( "io" "math" "math/big" + "sort" "strings" "sync" "time" @@ -32,14 +33,14 @@ import ( "golang.org/x/crypto/sha3" ) -const validatorsetABI = `[{"constant":true,"inputs":[{"name":"span","type":"uint256"}],"name":"getSpan","outputs":[{"name":"number","type":"uint256"},{"name":"startBlock","type":"uint256"},{"name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"span","type":"uint256"},{"name":"signer","type":"address"}],"name":"isProducer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"vote","type":"bytes"},{"name":"sigs","type":"bytes"},{"name":"txBytes","type":"bytes"},{"name":"proof","type":"bytes"}],"name":"commitSpan","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"span","type":"uint256"},{"name":"signer","type":"address"}],"name":"isValidator","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"left","type":"bytes32"},{"name":"right","type":"bytes32"}],"name":"innerNode","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"span","type":"uint256"}],"name":"getValidatorsTotalStakeBySpan","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"rootHash","type":"bytes32"},{"name":"leaf","type":"bytes32"},{"name":"proof","type":"bytes"}],"name":"checkMembership","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"CHAIN","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"span","type":"uint256"},{"name":"signer","type":"address"}],"name":"getValidatorBySigner","outputs":[{"components":[{"name":"id","type":"uint256"},{"name":"power","type":"uint256"},{"name":"signer","type":"address"}],"name":"result","type":"tuple"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentSpanNumber","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"d","type":"bytes32"}],"name":"leafNode","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"getNextSpan","outputs":[{"name":"number","type":"uint256"},{"name":"startBlock","type":"uint256"},{"name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitialValidators","outputs":[{"name":"","type":"address[]"},{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FIRST_END_BLOCK","outputs":[{"name":"","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"name":"producers","outputs":[{"name":"id","type":"uint256"},{"name":"power","type":"uint256"},{"name":"signer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"span","type":"uint256"},{"name":"dataHash","type":"bytes32"},{"name":"sigs","type":"bytes"}],"name":"getStakePower","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ROUND_TYPE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"span","type":"uint256"}],"name":"getProducersTotalStakeBySpan","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"BOR_ID","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentSpan","outputs":[{"name":"number","type":"uint256"},{"name":"startBlock","type":"uint256"},{"name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"sprint","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"name":"","type":"address[]"},{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"spanNumbers","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"vote","type":"bytes"},{"name":"sigs","type":"bytes"},{"name":"txBytes","type":"bytes"},{"name":"proof","type":"bytes"}],"name":"validateValidatorSet","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"VOTE_TYPE","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"name":"validators","outputs":[{"name":"id","type":"uint256"},{"name":"power","type":"uint256"},{"name":"signer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentSprint","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"spans","outputs":[{"name":"number","type":"uint256"},{"name":"startBlock","type":"uint256"},{"name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"uint256"},{"indexed":true,"name":"startBlock","type":"uint256"},{"indexed":true,"name":"endBlock","type":"uint256"}],"name":"NewSpan","type":"event"}]` +const validatorsetABI = `[{"constant":true,"inputs":[{"name":"span","type":"uint256"}],"name":"getSpan","outputs":[{"name":"number","type":"uint256"},{"name":"startBlock","type":"uint256"},{"name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"number","type":"uint256"}],"name":"getBorValidators","outputs":[{"name":"","type":"address[]"},{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"vote","type":"bytes"},{"name":"sigs","type":"bytes"},{"name":"txBytes","type":"bytes"},{"name":"proof","type":"bytes"}],"name":"commitSpan","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"currentSpanNumber","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNextSpan","outputs":[{"name":"number","type":"uint256"},{"name":"startBlock","type":"uint256"},{"name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitialValidators","outputs":[{"name":"","type":"address[]"},{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentSpan","outputs":[{"name":"number","type":"uint256"},{"name":"startBlock","type":"uint256"},{"name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"number","type":"uint256"}],"name":"getSpanByBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"name":"","type":"address[]"},{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"vote","type":"bytes"},{"name":"sigs","type":"bytes"},{"name":"txBytes","type":"bytes"},{"name":"proof","type":"bytes"}],"name":"validateValidatorSet","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]` const ( - voteSnapshotInterval = 1024 // Number of blocks after which to save the vote snapshot to the database - 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 vote snapshot to the database + 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 + wiggleTime = 5000 * time.Millisecond // Random delay (per signer) to allow concurrent signers ) // Bor protocol constants. @@ -49,13 +50,12 @@ var ( 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 - nonceAuthVote = hexutil.MustDecode("0xffffffffffffffff") // Magic nonce number to vote on adding a new signer - nonceDropVote = hexutil.MustDecode("0x0000000000000000") // Magic nonce number to vote on removing a signer. - uncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW. diffInTurn = big.NewInt(2) // Block difficulty for in-turn signatures diffNoTurn = big.NewInt(1) // Block difficulty for out-of-turn signatures + + validatorHeaderBytesLength = common.AddressLength + 20 // address + power ) // Various error messages to mark blocks invalid. These should be private to @@ -87,17 +87,17 @@ var ( // 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 + // errExtraValidators is returned if non-sprint-end block contain validator data in // their extra-data fields. - errExtraSigners = errors.New("non-checkpoint block contains extra signer list") + errExtraValidators = errors.New("non-sprint-end block contains extra validator 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") + // errInvalidSpanValidators is returned if a block contains an + // invalid list of validators (i.e. non divisible by 40 bytes). + errInvalidSpanValidators = errors.New("invalid validator list on sprint end 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") + // errMismatchingSprintValidators is returned if a sprint block contains a + // list of validators different than the one the local node calculated. + errMismatchingSprintValidators = errors.New("mismatching validator list on sprint block") // errInvalidMixDigest is returned if a block's mix digest is non-zero. errInvalidMixDigest = errors.New("non-zero mix digest") @@ -202,7 +202,6 @@ func CalcProducerDelay(snap *Snapshot, signer common.Address, period uint64, epo // if block is epoch start block, proposer will be inturn signer if (snap.Number+1)%epoch == 0 { - fmt.Println("==>", "producerDelay", producerDelay, "(snap.Number+1)%epoch", (snap.Number+1)%epoch) return producerDelay // if block is not epoch block, last block signer will be inturn @@ -317,18 +316,6 @@ func (c *Bor) verifyHeader(chain consensus.ChainReader, header *types.Header, pa if header.Time > uint64(time.Now().Unix()) { return consensus.ErrFutureBlock } - // Checkpoint blocks need to enforce zero beneficiary - checkpoint := (number % c.config.Sprint) == 0 - if checkpoint && header.Coinbase != (common.Address{}) { - return errInvalidCheckpointBeneficiary - } - // Nonces must be 0x00..0 or 0xff..f, zeroes enforced on checkpoints - if !bytes.Equal(header.Nonce[:], nonceAuthVote) && !bytes.Equal(header.Nonce[:], nonceDropVote) { - return errInvalidVote - } - if checkpoint && !bytes.Equal(header.Nonce[:], nonceDropVote) { - return errInvalidCheckpointVote - } // Check that the extra-data contains both the vanity and signature if len(header.Extra) < extraVanity { return errMissingVanity @@ -336,13 +323,17 @@ func (c *Bor) verifyHeader(chain consensus.ChainReader, header *types.Header, pa if len(header.Extra) < extraVanity+extraSeal { return errMissingSignature } + + // check extr adata + isSprintEnd := (number+1)%c.config.Sprint == 0 + // Ensure that the extra-data contains a signer list on checkpoint, but none otherwise signersBytes := len(header.Extra) - extraVanity - extraSeal - if !checkpoint && signersBytes != 0 { - return errExtraSigners + if !isSprintEnd && signersBytes != 0 { + return errExtraValidators } - if checkpoint && signersBytes%common.AddressLength != 0 { - return errInvalidCheckpointSigners + if isSprintEnd && signersBytes%validatorHeaderBytesLength != 0 { + return errInvalidSpanValidators } // Ensure that the mix digest is zero as we don't have fork protection currently if header.MixDigest != (common.Hash{}) { @@ -376,6 +367,7 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainReader, header *types.H if number == 0 { return nil } + // Ensure that the block's timestamp isn't too close to it's parent var parent *types.Header if len(parents) > 0 { @@ -383,30 +375,42 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainReader, header *types.H } else { parent = chain.GetHeader(header.ParentHash, number-1) } + if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash { return consensus.ErrUnknownAncestor } + if parent.Time+c.config.Period > header.Time { return ErrInvalidTimestamp } + // 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 - // } + snap, err := c.snapshot(chain, number-1, header.ParentHash, parents) + if err != nil { + return err + } - // If the block is a checkpoint block, verify the signer list - // TODO verify signers + // If the block is a sprint end block, verify the validator list if number%c.config.Sprint == 0 { - // signers := make([]byte, len(snap.Signers)*common.AddressLength) - // for i, signer := range snap.signers() { - // copy(signers[i*common.AddressLength:], signer[:]) - // } - // extraSuffix := len(header.Extra) - extraSeal - // if !bytes.Equal(header.Extra[extraVanity:extraSuffix], signers) { - // return errMismatchingCheckpointSigners - // } + validatorsBytes := make([]byte, len(snap.ValidatorSet.Validators)*validatorHeaderBytesLength) + + currentValidators := snap.ValidatorSet.Copy().Validators + // sort validator by address + sort.Sort(ValidatorsByAddress(currentValidators)) + for i, validator := range currentValidators { + copy(validatorsBytes[i*validatorHeaderBytesLength:], validator.HeaderBytes()) + } + + extraSuffix := len(header.Extra) - extraSeal + + // fmt.Println("validatorsBytes ==> verify seal ==> ", hex.EncodeToString(validatorsBytes)) + // fmt.Println("header.Extra ==> verify seal ==> ", hex.EncodeToString(header.Extra[extraVanity:extraSuffix])) + + if !bytes.Equal(header.Extra[extraVanity:extraSuffix], validatorsBytes) { + // return errMismatchingSprintValidators + } } + // All basic checks passed, verify the seal and return return c.verifySeal(chain, header, parents) } @@ -418,39 +422,41 @@ func (c *Bor) snapshot(chain consensus.ChainReader, number uint64, hash common.H 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%voteSnapshotInterval == 0 { + if number%checkpointInterval == 0 { if s, err := loadSnapshot(c.config, c.signatures, c.db, hash, c.ethAPI); err == nil { - log.Trace("Loaded voting snapshot from disk", "number", number, "hash", hash) + log.Trace("Loaded snapshot from disk", "number", number, "hash", hash) snap = s break } } - // If we're at an checkpoint block, make a snapshot if it's known - if number == 0 || (number%c.config.Sprint == 0 && chain.GetHeaderByNumber(number-1) == nil) { + // If we're at the genesis, snapshot the initial state. Alternatively if we're + // at a checkpoint block without a parent (light client CHT), or we have piled + // up more headers than allowed to be reorged (chain reinit from a freezer), + // consider the checkpoint trusted and snapshot it. + // TODO fix this + if number == 0 /* || (number%c.config.Sprint == 0 && (len(headers) > params.ImmutabilityThreshold || chain.GetHeaderByNumber(number-1) == nil)) */ { checkpoint := chain.GetHeaderByNumber(number) if checkpoint != nil { + // get checkpoint data hash := checkpoint.Hash() // current validators - validators, err := c.GetCurrentValidators(number) + validators, err := c.GetCurrentValidators(number, number+1) if err != nil { - // Handle error - } - - // TODO remove signer - signers := make([]common.Address, (len(checkpoint.Extra)-extraVanity-extraSeal)/common.AddressLength) - for i := 0; i < len(signers); i++ { - copy(signers[i][:], checkpoint.Extra[extraVanity+i*common.AddressLength:]) + 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 @@ -459,6 +465,7 @@ func (c *Bor) snapshot(chain consensus.ChainReader, number uint64, hash common.H break } } + // No snapshot for this header, gather the header and move backward var header *types.Header if len(parents) > 0 { @@ -478,10 +485,17 @@ func (c *Bor) snapshot(chain consensus.ChainReader, number uint64, hash common.H 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) if err != nil { return nil, err @@ -489,11 +503,11 @@ func (c *Bor) snapshot(chain consensus.ChainReader, number uint64, hash common.H c.recents.Add(snap.Hash, snap) // If we've generated a new checkpoint snapshot, save to disk - if snap.Number%voteSnapshotInterval == 0 && len(headers) > 0 { + if snap.Number%checkpointInterval == 0 && len(headers) > 0 { if err = snap.store(c.db); err != nil { return nil, err } - log.Trace("Stored voting snapshot to disk", "number", snap.Number, "hash", snap.Hash) + log.Trace("Stored snapshot to disk", "number", snap.Number, "hash", snap.Hash) } return snap, err } @@ -570,7 +584,6 @@ func (c *Bor) verifySeal(chain consensus.ChainReader, header *types.Header, pare } } - fmt.Println("==> New block", "number", header.Number, "hash", header.Hash().Hex(), "signer", signer.Hex(), "proposer", proposer.Hex()) return nil } @@ -582,7 +595,7 @@ func (c *Bor) Prepare(chain consensus.ChainReader, header *types.Header) error { header.Nonce = types.BlockNonce{} number := header.Number.Uint64() - // Assemble the voting snapshot to check which votes make sense + // Assemble the validator snapshot to check which votes make sense snap, err := c.snapshot(chain, number-1, header.ParentHash, nil) if err != nil { return err @@ -597,11 +610,21 @@ func (c *Bor) Prepare(chain consensus.ChainReader, header *types.Header) error { } header.Extra = header.Extra[:extraVanity] - if number%c.config.Sprint == 0 { - for _, signer := range snap.signers() { - header.Extra = append(header.Extra, signer[:]...) + // get validator set if number + if (number+1)%c.config.Sprint == 0 { + newValidators, err := c.GetCurrentValidators(snap.Number, number+1) + if err != nil { + return errors.New("unknown validators") + } + + // sort validator by address + sort.Sort(ValidatorsByAddress(newValidators)) + for _, validator := range newValidators { + header.Extra = append(header.Extra, validator.HeaderBytes()...) } } + + // add extra seal space header.Extra = append(header.Extra, make([]byte, extraSeal)...) // Mix digest is reserved for now, set to empty @@ -617,7 +640,6 @@ func (c *Bor) Prepare(chain consensus.ChainReader, header *types.Header) error { if header.Time < uint64(time.Now().Unix()) { header.Time = uint64(time.Now().Unix()) } - fmt.Println("parent.Time", parent.Time, "header.Time", header.Time, "number", header.Number) return nil } @@ -686,6 +708,7 @@ func (c *Bor) Seal(chain consensus.ChainReader, block *types.Block, results chan if number%c.config.Sprint != 0 { // proposer = snap.Recents[number-1] } + proposerIndex, _ := snap.ValidatorSet.GetByAddress(proposer) signerIndex, _ := snap.ValidatorSet.GetByAddress(signer) limit := len(validators) - (len(validators)/2 + 1) @@ -695,7 +718,7 @@ func (c *Bor) Seal(chain consensus.ChainReader, block *types.Block, results chan if tempIndex < proposerIndex { tempIndex = tempIndex + len(validators) } - fmt.Println("Block temp index", "number", number, "tempIndex", tempIndex, "proposerIndex", proposerIndex) + if limit > 0 && tempIndex-proposerIndex > limit { log.Info("Signed recently, must wait for others") return nil @@ -703,11 +726,11 @@ func (c *Bor) Seal(chain consensus.ChainReader, block *types.Block, results chan // 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 - wiggle := time.Duration(wiggleTime) * time.Duration(tempIndex-proposerIndex) + wiggle := time.Duration(2*c.config.Period) * time.Second * time.Duration(tempIndex-proposerIndex) delay += wiggle fmt.Println("Out-of-turn signing requested", "wiggle", common.PrettyDuration(wiggle)) - fmt.Println("--> Sealing block with", "number", number, "delay", delay, "headerDifficulty", header.Difficulty, "signer", signer.Hex(), "proposer", proposer.Hex()) + fmt.Println("Sealing block with", "number", number, "delay", delay, "headerDifficulty", header.Difficulty, "signer", signer.Hex(), "proposer", proposer.Hex()) // Sign all the things! sighash, err := signFn(accounts.Account{Address: signer}, accounts.MimetypeBor, BorRLP(header)) @@ -768,64 +791,22 @@ func (c *Bor) Close() error { } // GetCurrentValidators get current validators -func (c *Bor) GetCurrentValidators(number uint64) ([]*Validator, error) { - return GetValidators(number, c.config.Sprint, c.config.ValidatorContract, c.ethAPI) +func (c *Bor) GetCurrentValidators(snapshotNumber uint64, blockNumber uint64) ([]*Validator, error) { + return GetValidators(snapshotNumber, blockNumber, c.config.Sprint, c.config.ValidatorContract, c.ethAPI) } // GetValidators get current validators -func GetValidators(number uint64, sprint uint64, validatorContract string, ethAPI *ethapi.PublicBlockChainAPI) ([]*Validator, error) { - blockNr := rpc.BlockNumber(number) +func GetValidators(snapshotNumber uint64, blockNumber uint64, sprint uint64, validatorContract string, ethAPI *ethapi.PublicBlockChainAPI) ([]*Validator, error) { + // block + blockNr := rpc.BlockNumber(snapshotNumber) // validator set ABI validatorSetABI, _ := abi.JSON(strings.NewReader(validatorsetABI)) - // First End block - getFirstEndBlock := func() (uint64, error) { - data, err := validatorSetABI.Pack("FIRST_END_BLOCK") - if err != nil { - return 0, err - } - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() // cancel when we are finished consuming integers - - // call - msgData := (hexutil.Bytes)(data) - toAddress := common.HexToAddress(validatorContract) - gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2)) - result, err := ethAPI.Call(ctx, ethapi.CallArgs{ - Gas: &gas, - To: &toAddress, - Data: &msgData, - }, blockNr) - if err != nil { - return 0, err - } - - var ( - ret0 = new(uint64) - ) - out := ret0 - - if err := validatorSetABI.Unpack(&out, "FIRST_END_BLOCK", result); err != nil { - return 0, err - } - return *ret0, nil - - } - - firstEndBlock, err := getFirstEndBlock() - if err != nil { - panic(err) - } - // method - method := "getValidators" - if number <= firstEndBlock { - method = "getInitialValidators" - } + method := "getBorValidators" - data, err := validatorSetABI.Pack(method) + data, err := validatorSetABI.Pack(method, big.NewInt(0).SetUint64(blockNumber)) if err != nil { fmt.Println("Unable to pack tx for getValidator", "error", err) return nil, err @@ -844,7 +825,8 @@ func GetValidators(number uint64, sprint uint64, validatorContract string, ethAP Data: &msgData, }, blockNr) if err != nil { - return nil, err + panic(err) + // return nil, err } var ( @@ -857,7 +839,6 @@ func GetValidators(number uint64, sprint uint64, validatorContract string, ethAP } if err := validatorSetABI.Unpack(out, method, result); err != nil { - fmt.Println("err", err) return nil, err } @@ -869,8 +850,6 @@ func GetValidators(number uint64, sprint uint64, validatorContract string, ethAP } } - fmt.Println(method) - fmt.Println(" === ", valz) return valz, nil } diff --git a/consensus/bor/snapshot.go b/consensus/bor/snapshot.go index 94431c8841fe153d924684482d2e84e69234a01e..b55fa8c9ea8c0b6d6c6454d5b2af76e51a498dda 100644 --- a/consensus/bor/snapshot.go +++ b/consensus/bor/snapshot.go @@ -80,7 +80,6 @@ func newSnapshot(config *params.BorConfig, sigcache *lru.ARCCache, number uint64 Recents: make(map[uint64]common.Address), // Tally: make(map[common.Address]Tally), } - fmt.Println("New validator set", "number", number, "proposer", snap.ValidatorSet.Proposer.Address.Hex()) return snap } @@ -98,6 +97,9 @@ func loadSnapshot(config *params.BorConfig, sigcache *lru.ARCCache, db ethdb.Dat snap.sigcache = sigcache snap.ethAPI = ethAPI + // update total voting power + snap.ValidatorSet.updateTotalVotingPower() + return snap, nil } @@ -126,10 +128,6 @@ func (s *Snapshot) copy() *Snapshot { for block, signer := range s.Recents { cpy.Recents[block] = signer } - // for address, tally := range s.Tally { - // cpy.Tally[address] = tally - // } - // copy(cpy.Votes, s.Votes) return cpy } @@ -198,10 +196,6 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) { for _, header := range headers { // Remove any votes on checkpoint blocks number := header.Number.Uint64() - if (number+1)%s.config.Sprint == 0 { - // snap.Votes = nil - // snap.Tally = make(map[common.Address]Tally) - } // Delete the oldest signer from the recent list to allow it signing again if number >= s.config.Sprint && number-s.config.Sprint >= 0 { @@ -214,6 +208,18 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) { return nil, err } + // change validator set and change proposer + if number > 0 && (number+1)%s.config.Sprint == 0 { + validatorBytes := header.Extra[extraVanity : len(header.Extra)-extraSeal] + + // newVals, _ := GetValidators(number, number+1, s.config.Sprint, s.config.ValidatorContract, snap.ethAPI) + newVals, _ := ParseValidators(validatorBytes) + v := getUpdatedValidatorSet(snap.ValidatorSet.Copy(), newVals) + v.IncrementProposerPriority(1) + snap.ValidatorSet = v + } + + // check if signer is in validator set if !snap.ValidatorSet.HasAddress(signer.Bytes()) { return nil, errUnauthorizedSigner } @@ -248,80 +254,12 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) { snap.Recents[number] = signer // TODO remove fmt.Println("Recent signer", "number", number, "signer", signer.Hex()) - // change proposer on epoch - if number > 0 && (number+1)%s.config.Sprint == 0 { - newVals, _ := GetValidators(number, s.config.Sprint, s.config.ValidatorContract, snap.ethAPI) - v := getUpdatedValidatorSet(snap.ValidatorSet.Copy(), newVals) - v.IncrementProposerPriority(1) - snap.ValidatorSet = v - fmt.Println("New validator set", "number", number, "proposer", v.Proposer.Address.Hex()) - } - // // Header authorized, discard any previous votes from the signer - // for i, vote := range snap.Votes { - // if vote.Signer == signer && vote.Address == header.Coinbase { - // // Uncast the vote from the cached tally - // snap.uncast(vote.Address, vote.Authorize) - - // // Uncast the vote from the chronological list - // snap.Votes = append(snap.Votes[:i], snap.Votes[i+1:]...) - // break // only one vote allowed - // } - // } - // Tally up the new vote from the signer - // var authorize bool - // switch { - // case bytes.Equal(header.Nonce[:], nonceAuthVote): - // authorize = true - // case bytes.Equal(header.Nonce[:], nonceDropVote): - // authorize = false - // default: - // return nil, errInvalidVote - // } - // if snap.cast(header.Coinbase, authorize) { - // snap.Votes = append(snap.Votes, &Vote{ - // Signer: signer, - // Block: number, - // Address: header.Coinbase, - // Authorize: authorize, - // }) - // } - // If the vote passed, update the list of signers - // if tally := snap.Tally[header.Coinbase]; tally.Votes > len(snap.Signers)/2 { - // if tally.Authorize { - // snap.Signers[header.Coinbase] = struct{}{} - // } else { - // delete(snap.Signers, header.Coinbase) - - // // Signer list shrunk, delete any leftover recent caches - // if limit := uint64(len(snap.Signers)/2 + 1); number >= limit { - // delete(snap.Recents, number-limit) - // } - // // Discard any previous votes the deauthorized signer cast - // for i := 0; i < len(snap.Votes); i++ { - // if snap.Votes[i].Signer == header.Coinbase { - // // Uncast the vote from the cached tally - // snap.uncast(snap.Votes[i].Address, snap.Votes[i].Authorize) - - // // Uncast the vote from the chronological list - // snap.Votes = append(snap.Votes[:i], snap.Votes[i+1:]...) - - // i-- - // } - // } - // } - // // Discard any previous votes around the just changed account - // for i := 0; i < len(snap.Votes); i++ { - // if snap.Votes[i].Address == header.Coinbase { - // snap.Votes = append(snap.Votes[:i], snap.Votes[i+1:]...) - // i-- - // } - // } - // delete(snap.Tally, header.Coinbase) - // } } snap.Number += uint64(len(headers)) snap.Hash = headers[len(headers)-1].Hash() + fmt.Println("Current validator set", "number", snap.Number, "validatorSet", snap.ValidatorSet) + return snap, nil } diff --git a/consensus/bor/validator.go b/consensus/bor/validator.go index 14d9de3d2f723bbb593e61d477271d5d447d7d5b..32934ea2d4ab96cd128f7bc3c7edf0b4e0360d01 100644 --- a/consensus/bor/validator.go +++ b/consensus/bor/validator.go @@ -3,7 +3,9 @@ package bor import ( "bytes" "encoding/json" + "errors" "fmt" + "math/big" "strings" "github.com/ethereum/go-ethereum/common" @@ -86,3 +88,39 @@ func (v *Validator) Bytes() []byte { } return nil } + +// HeaderBytes return header bytes +func (v *Validator) HeaderBytes() []byte { + result := make([]byte, 40) + copy(result[:20], v.Address.Bytes()) + copy(result[20:], v.PowerBytes()) + return result +} + +// PowerBytes return power bytes +func (v *Validator) PowerBytes() []byte { + powerBytes := big.NewInt(0).SetInt64(v.VotingPower).Bytes() + result := make([]byte, 20) + copy(result[20-len(powerBytes):], powerBytes) + return result +} + +// ParseValidators returns validator set bytes +func ParseValidators(validatorsBytes []byte) ([]*Validator, error) { + if len(validatorsBytes)%40 != 0 { + return nil, errors.New("Invalid validators bytes") + } + + result := make([]*Validator, len(validatorsBytes)/40) + for i := 0; i < len(validatorsBytes); i += 40 { + address := make([]byte, 20) + power := make([]byte, 20) + + copy(address, validatorsBytes[i:i+20]) + copy(power, validatorsBytes[i+20:i+40]) + + result[i/40] = NewValidator(common.BytesToAddress(address), big.NewInt(0).SetBytes(power).Int64()) + } + + return result, nil +}