WIP. Blockchain creation works in simple cases but still very buggy.

This commit is contained in:
Dan Laine 2020-03-16 17:21:38 -04:00
parent 45805cbac7
commit 5ca0a909e4
6 changed files with 68 additions and 4 deletions

View File

@ -92,6 +92,7 @@ type manager struct {
// That is, [chainID].String() is an alias for the chain, too // That is, [chainID].String() is an alias for the chain, too
ids.Aliaser ids.Aliaser
stakingEnabled bool // True iff the network has staking enabled
log logging.Logger log logging.Logger
logFactory logging.Factory logFactory logging.Factory
vmManager vms.Manager // Manage mappings from vm ID --> vm vmManager vms.Manager // Manage mappings from vm ID --> vm
@ -120,6 +121,7 @@ type manager struct {
// <validators> validate this chain // <validators> validate this chain
// TODO: Make this function take less arguments // TODO: Make this function take less arguments
func New( func New(
stakingEnabled bool,
log logging.Logger, log logging.Logger,
logFactory logging.Factory, logFactory logging.Factory,
vmManager vms.Manager, vmManager vms.Manager,
@ -143,6 +145,7 @@ func New(
router.Initialize(log, &timeoutManager) router.Initialize(log, &timeoutManager)
m := &manager{ m := &manager{
stakingEnabled: stakingEnabled,
log: log, log: log,
logFactory: logFactory, logFactory: logFactory,
vmManager: vmManager, vmManager: vmManager,
@ -256,7 +259,13 @@ func (m *manager) ForceCreateChain(chain ChainParameters) {
} }
// The validators of this blockchain // The validators of this blockchain
validators, ok := m.validators.GetValidatorSet(ids.Empty) // TODO: Change argument to chain.SubnetID var validators validators.Set // Validators validating this blockchain
var ok bool
if m.stakingEnabled {
validators, ok = m.validators.GetValidatorSet(chain.SubnetID)
} else { // Staking is disabled. Every peer validates every subnet.
validators, ok = m.validators.GetValidatorSet(ids.Empty) // ids.Empty is the default subnet ID. TODO: Move to const package so we can use it here.
}
if !ok { if !ok {
m.log.Error("couldn't get validator set of subnet with ID %s. The subnet may not exist", chain.SubnetID) m.log.Error("couldn't get validator set of subnet with ID %s. The subnet may not exist", chain.SubnetID)
return return
@ -353,7 +362,7 @@ func (m *manager) createAvalancheChain(
msgChan := make(chan common.Message, defaultChannelSize) msgChan := make(chan common.Message, defaultChannelSize)
if err := vm.Initialize(ctx, vmDB, genesisData, msgChan, fxs); err != nil { if err := vm.Initialize(ctx, vmDB, genesisData, msgChan, fxs); err != nil {
return err return fmt.Errorf("error during vm's Initialize: %v", err)
} }
// Handles serialization/deserialization of vertices and also the // Handles serialization/deserialization of vertices and also the

View File

@ -342,6 +342,7 @@ func Genesis(networkID uint32) ([]byte, error) {
platformvmArgs.Chains = []platformvm.APIChain{ platformvmArgs.Chains = []platformvm.APIChain{
platformvm.APIChain{ platformvm.APIChain{
GenesisData: avmReply.Bytes, GenesisData: avmReply.Bytes,
SubnetID: platformvm.DefaultSubnetID,
VMID: avm.ID, VMID: avm.ID,
FxIDs: []ids.ID{ FxIDs: []ids.ID{
secp256k1fx.ID, secp256k1fx.ID,
@ -350,21 +351,25 @@ func Genesis(networkID uint32) ([]byte, error) {
}, },
platformvm.APIChain{ platformvm.APIChain{
GenesisData: evmReply, GenesisData: evmReply,
SubnetID: platformvm.DefaultSubnetID,
VMID: evm.ID, VMID: evm.ID,
Name: "Athereum", Name: "Athereum",
}, },
platformvm.APIChain{ platformvm.APIChain{
GenesisData: spdagvmReply.Bytes, GenesisData: spdagvmReply.Bytes,
SubnetID: platformvm.DefaultSubnetID,
VMID: spdagvm.ID, VMID: spdagvm.ID,
Name: "Simple DAG Payments", Name: "Simple DAG Payments",
}, },
platformvm.APIChain{ platformvm.APIChain{
GenesisData: spchainvmReply.Bytes, GenesisData: spchainvmReply.Bytes,
SubnetID: platformvm.DefaultSubnetID,
VMID: spchainvm.ID, VMID: spchainvm.ID,
Name: "Simple Chain Payments", Name: "Simple Chain Payments",
}, },
platformvm.APIChain{ platformvm.APIChain{
GenesisData: formatting.CB58{Bytes: []byte{}}, // There is no genesis data GenesisData: formatting.CB58{Bytes: []byte{}}, // There is no genesis data
SubnetID: platformvm.DefaultSubnetID,
VMID: timestampvm.ID, VMID: timestampvm.ID,
Name: "Simple Timestamp Server", Name: "Simple Timestamp Server",
}, },

View File

@ -351,8 +351,13 @@ func (n *Node) initChains() {
n.Log.Info("initializing chains") n.Log.Info("initializing chains")
vdrs := n.vdrs vdrs := n.vdrs
// If staking is disabled, ignore updates to Subnets' validator sets
// Instead of updating node's validator manager, platform chain makes changes
// to its own local validator manager (which isn't used for sampling)
if !n.Config.EnableStaking { if !n.Config.EnableStaking {
defaultSubnetValidators := validators.NewSet() defaultSubnetValidators := validators.NewSet()
defaultSubnetValidators.Add(validators.NewValidator(n.ID, 1))
vdrs = validators.NewManager() vdrs = validators.NewManager()
vdrs.PutValidatorSet(platformvm.DefaultSubnetID, defaultSubnetValidators) vdrs.PutValidatorSet(platformvm.DefaultSubnetID, defaultSubnetValidators)
} }
@ -375,6 +380,7 @@ func (n *Node) initChains() {
// Create the Platform Chain // Create the Platform Chain
n.chainManager.ForceCreateChain(chains.ChainParameters{ n.chainManager.ForceCreateChain(chains.ChainParameters{
ID: ids.Empty, ID: ids.Empty,
SubnetID: platformvm.DefaultSubnetID,
GenesisData: genesisBytes, // Specifies other chains to create GenesisData: genesisBytes, // Specifies other chains to create
VMAlias: platformvm.ID.String(), VMAlias: platformvm.ID.String(),
CustomBeacons: beacons, CustomBeacons: beacons,
@ -404,6 +410,7 @@ func (n *Node) initAPIServer() {
// Assumes n.DB, n.vdrs all initialized (non-nil) // Assumes n.DB, n.vdrs all initialized (non-nil)
func (n *Node) initChainManager() { func (n *Node) initChainManager() {
n.chainManager = chains.New( n.chainManager = chains.New(
n.Config.EnableStaking,
n.Log, n.Log,
n.LogFactory, n.LogFactory,
n.vmManager, n.vmManager,

View File

@ -7,6 +7,8 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/ava-labs/gecko/snow/validators"
"github.com/ava-labs/gecko/database" "github.com/ava-labs/gecko/database"
"github.com/ava-labs/gecko/ids" "github.com/ava-labs/gecko/ids"
@ -128,7 +130,12 @@ func (tx *CreateSubnetTx) SemanticVerify(db database.Database) (func(), error) {
return nil, err return nil, err
} }
return nil, nil // Register new subnet in validator manager
onAccept := func() {
tx.vm.Validators.PutValidatorSet(tx.ID, validators.NewSet())
}
return onAccept, nil
} }
// Bytes returns the byte representation of [tx] // Bytes returns the byte representation of [tx]

View File

@ -845,6 +845,14 @@ func (service *Service) IssueTx(_ *http.Request, args *IssueTxArgs, response *Is
defer service.vm.resetTimer() defer service.vm.resetTimer()
response.TxID = tx.ID response.TxID = tx.ID
return nil return nil
case *CreateChainTx:
if err := tx.initialize(service.vm); err != nil {
return fmt.Errorf("error initializing tx: %s", err)
}
service.vm.unissuedDecisionTxs = append(service.vm.unissuedDecisionTxs, tx)
defer service.vm.resetTimer()
response.TxID = tx.ID()
return nil
default: default:
return errors.New("Could not parse given tx. Must be one of: addDefaultSubnetValidatorTx, addDefaultSubnetDelegatorTx, addNonDefaultSubnetValidatorTx, createSubnetTx") return errors.New("Could not parse given tx. Must be one of: addDefaultSubnetValidatorTx, addDefaultSubnetDelegatorTx, addNonDefaultSubnetValidatorTx, createSubnetTx")
} }

View File

@ -265,8 +265,13 @@ func (vm *VM) Initialize(
}) })
go ctx.Log.RecoverAndPanic(vm.timer.Dispatch) go ctx.Log.RecoverAndPanic(vm.timer.Dispatch)
if err := vm.initValidators(); err != nil {
ctx.Log.Error("failed to initialize validator manager: %s", err)
return err
}
if err := vm.updateValidators(DefaultSubnetID); err != nil { if err := vm.updateValidators(DefaultSubnetID); err != nil {
ctx.Log.Error("failed to initialize the current validator set: %s", err) ctx.Log.Error("failed to initialize default Subnet validator set: %s", err)
return err return err
} }
@ -292,6 +297,7 @@ func (vm *VM) initBlockchains() error {
for _, chain := range existingChains { // Create each blockchain for _, chain := range existingChains { // Create each blockchain
chainParams := chains.ChainParameters{ chainParams := chains.ChainParameters{
ID: chain.ID(), ID: chain.ID(),
SubnetID: chain.SubnetID,
GenesisData: chain.GenesisData, GenesisData: chain.GenesisData,
VMAlias: chain.VMID.String(), VMAlias: chain.VMID.String(),
} }
@ -303,6 +309,27 @@ func (vm *VM) initBlockchains() error {
return nil return nil
} }
// Set the node's validator manager to be up to date
func (vm *VM) initValidators() error {
vm.Ctx.Log.Verbo("platform chain initializing Subnet validators")
subnets, err := vm.getSubnets(vm.DB)
if err != nil {
return err
}
if err := vm.updateValidators(DefaultSubnetID); err != nil {
return err
}
for _, subnet := range subnets {
if err := vm.updateValidators(subnet.ID); err != nil {
return err
}
}
return nil
}
// Shutdown this blockchain // Shutdown this blockchain
func (vm *VM) Shutdown() { func (vm *VM) Shutdown() {
vm.timer.Stop() vm.timer.Stop()
@ -671,6 +698,7 @@ func (vm *VM) getValidators(validatorEvents *EventHeap) []validators.Validator {
return vdrList return vdrList
} }
// Update the node's validator manager to reflect the current validator set of the given Subnet
func (vm *VM) updateValidators(subnetID ids.ID) error { func (vm *VM) updateValidators(subnetID ids.ID) error {
validatorSet, ok := vm.Validators.GetValidatorSet(subnetID) validatorSet, ok := vm.Validators.GetValidatorSet(subnetID)
if !ok { if !ok {