mirror of https://github.com/poanetwork/gecko.git
when a node joins a Subnet it creates all of the blockchains the Subnet is validating
This commit is contained in:
parent
eb5851431d
commit
1f871c097d
|
@ -7,6 +7,8 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/ava-labs/gecko/ids"
|
||||
|
||||
"github.com/ava-labs/gecko/database"
|
||||
"github.com/ava-labs/gecko/database/versiondb"
|
||||
)
|
||||
|
@ -86,7 +88,7 @@ func (tx *advanceTimeTx) SemanticVerify(db database.Database) (*versiondb.Databa
|
|||
return nil, nil, nil, nil, err
|
||||
}
|
||||
|
||||
current, pending, err := tx.vm.calculateValidators(db, tx.Timestamp(), DefaultSubnetID)
|
||||
current, pending, _, _, err := tx.vm.calculateValidators(db, tx.Timestamp(), DefaultSubnetID)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
|
@ -98,29 +100,35 @@ func (tx *advanceTimeTx) SemanticVerify(db database.Database) (*versiondb.Databa
|
|||
return nil, nil, nil, nil, err
|
||||
}
|
||||
|
||||
// For each subnet, calculate what current and pending validator sets should be
|
||||
// For each Subnet, calculate what current and pending validator sets should be
|
||||
// given new timestamp
|
||||
|
||||
// Key: Subnet ID
|
||||
// Value: IDs of validators that will have started validating this Subnet when
|
||||
// timestamp is advanced to tx.Timestamp()
|
||||
startedValidating := make(map[ids.ID]ids.ShortSet, 0)
|
||||
subnets, err := tx.vm.getSubnets(db)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
for _, subnet := range subnets {
|
||||
current, pending, err := tx.vm.calculateValidators(db, tx.Timestamp(), subnet.id)
|
||||
current, pending, started, _, err := tx.vm.calculateValidators(db, tx.Timestamp(), subnet.id)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
|
||||
if err := tx.vm.putCurrentValidators(onCommitDB, current, subnet.id); err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
if err := tx.vm.putPendingValidators(onCommitDB, pending, subnet.id); err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
startedValidating[subnet.ID()] = started
|
||||
}
|
||||
|
||||
// If this block is committed, update the validator sets
|
||||
// onAbortDB or onCommitDB should commit (flush to vm.DB) before this is called
|
||||
updateValidators := func() {
|
||||
onCommitFunc := func() {
|
||||
// For each Subnet, update the node's validator manager to reflect current Subnet membership
|
||||
subnets, err := tx.vm.getSubnets(tx.vm.DB)
|
||||
if err != nil {
|
||||
tx.vm.Ctx.Log.Error("failed to get subnets: %s", err)
|
||||
|
@ -128,18 +136,35 @@ func (tx *advanceTimeTx) SemanticVerify(db database.Database) (*versiondb.Databa
|
|||
}
|
||||
for _, subnet := range subnets {
|
||||
if err := tx.vm.updateValidators(subnet.id); err != nil {
|
||||
tx.vm.Ctx.Log.Debug("failed to update validators on the default subnet: %s", err)
|
||||
tx.vm.Ctx.Log.Debug("failed to update Subnet %s: %s", subnet.id, err)
|
||||
}
|
||||
}
|
||||
if err := tx.vm.updateValidators(DefaultSubnetID); err != nil {
|
||||
tx.vm.Ctx.Log.Fatal("failed to update validators on the default subnet: %s", err)
|
||||
tx.vm.Ctx.Log.Fatal("failed to update Default Subnet: %s", err)
|
||||
}
|
||||
|
||||
// If this node started validating a Subnet, create the blockchains that the Subnet validates
|
||||
chains, err := tx.vm.getChains(tx.vm.DB) // all blockchains
|
||||
if err != nil {
|
||||
tx.vm.Ctx.Log.Error("couldn't get blockchains: %s", err)
|
||||
return
|
||||
}
|
||||
for subnetID, validatorIDs := range startedValidating {
|
||||
if !validatorIDs.Contains(tx.vm.Ctx.NodeID) {
|
||||
continue
|
||||
}
|
||||
for _, chain := range chains {
|
||||
if chain.SubnetID.Equals(subnetID) {
|
||||
tx.vm.createChain(chain)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Specify what the state of the chain will be if this proposal is aborted
|
||||
onAbortDB := versiondb.New(db) // state doesn't change
|
||||
|
||||
return onCommitDB, onAbortDB, updateValidators, nil, nil
|
||||
return onCommitDB, onAbortDB, onCommitFunc, nil, nil
|
||||
}
|
||||
|
||||
// InitiallyPrefersCommit returns true if the proposed time isn't after the
|
||||
|
|
|
@ -194,7 +194,8 @@ func (tx *CreateChainTx) SemanticVerify(db database.Database) (func(), error) {
|
|||
}
|
||||
}
|
||||
|
||||
// If this proposal is committed, create the new blockchain using the chain manager
|
||||
// If this proposal is committed and this node is a member of the
|
||||
// subnet that validates the blockchain, create the blockchain
|
||||
onAccept := func() {
|
||||
tx.vm.createChain(tx)
|
||||
}
|
||||
|
|
|
@ -291,7 +291,7 @@ func (vm *VM) initBlockchains() error {
|
|||
return err
|
||||
}
|
||||
|
||||
for _, chain := range blockchains { // Create each blockchain
|
||||
for _, chain := range blockchains {
|
||||
vm.createChain(chain)
|
||||
}
|
||||
return nil
|
||||
|
@ -325,6 +325,7 @@ func (vm *VM) createChain(tx *CreateChainTx) {
|
|||
validators, subnetExists := vm.Validators.GetValidatorSet(tx.SubnetID)
|
||||
if !subnetExists {
|
||||
vm.Ctx.Log.Error("blockchain %s validated by Subnet %s but couldn't get that Subnet. Blockchain not created")
|
||||
return
|
||||
}
|
||||
if !validators.Contains(vm.Ctx.NodeID) { // This node doesn't validate this blockchain
|
||||
return
|
||||
|
@ -653,13 +654,16 @@ func (vm *VM) nextSubnetValidatorChangeTime(db database.Database, subnetID ids.I
|
|||
// Returns:
|
||||
// 1) The validator set of subnet with ID [subnetID] when timestamp is advanced to [timestamp]
|
||||
// 2) The pending validator set of subnet with ID [subnetID] when timestamp is advanced to [timestamp]
|
||||
// 3) The IDs of the validators that start validating [subnetID] between now and [timestamp]
|
||||
// 4) The IDs of the validators that stop validating [subnetID] between now and [timestamp]
|
||||
// Note that this method will not remove validators from the current validator set of the default subnet.
|
||||
// That happens in reward blocks.
|
||||
func (vm *VM) calculateValidators(db database.Database, timestamp time.Time, subnetID ids.ID) (current, pending *EventHeap, err error) {
|
||||
func (vm *VM) calculateValidators(db database.Database, timestamp time.Time, subnetID ids.ID) (current,
|
||||
pending *EventHeap, started, stopped ids.ShortSet, err error) {
|
||||
// remove validators whose end time <= [timestamp]
|
||||
current, err = vm.getCurrentValidators(db, subnetID)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
if !subnetID.Equals(DefaultSubnetID) { // validators of default subnet removed in rewardValidatorTxs, not here
|
||||
for current.Len() > 0 {
|
||||
|
@ -668,11 +672,12 @@ func (vm *VM) calculateValidators(db database.Database, timestamp time.Time, sub
|
|||
break
|
||||
}
|
||||
current.Remove()
|
||||
stopped.Add(next.Vdr().ID())
|
||||
}
|
||||
}
|
||||
pending, err = vm.getPendingValidators(db, subnetID)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
for pending.Len() > 0 {
|
||||
nextTx := pending.Peek() // pending staker with earliest start time
|
||||
|
@ -681,8 +686,9 @@ func (vm *VM) calculateValidators(db database.Database, timestamp time.Time, sub
|
|||
}
|
||||
heap.Push(current, nextTx)
|
||||
heap.Pop(pending)
|
||||
started.Add(nextTx.Vdr().ID())
|
||||
}
|
||||
return current, pending, nil
|
||||
return current, pending, started, stopped, nil
|
||||
}
|
||||
|
||||
func (vm *VM) getValidators(validatorEvents *EventHeap) []validators.Validator {
|
||||
|
|
Loading…
Reference in New Issue