core: cache standby validators in the Blockchain

They never change, so it makes no sense parsing the keys over and over
again. It also simplifies the interface a little.
This commit is contained in:
Roman Khimov 2020-06-23 18:15:55 +03:00
parent cd2dca0259
commit e5f05790d5
9 changed files with 21 additions and 22 deletions

View file

@ -117,6 +117,8 @@ type Blockchain struct {
// cache for block verification keys. // cache for block verification keys.
keyCache map[util.Uint160]map[string]*keys.PublicKey keyCache map[util.Uint160]map[string]*keys.PublicKey
sbValidators keys.PublicKeys
log *zap.Logger log *zap.Logger
lastBatch *storage.MemBatch lastBatch *storage.MemBatch
@ -152,6 +154,10 @@ func NewBlockchain(s storage.Store, cfg config.ProtocolConfiguration, log *zap.L
cfg.MemPoolSize = defaultMemPoolSize cfg.MemPoolSize = defaultMemPoolSize
log.Info("mempool size is not set or wrong, setting default value", zap.Int("MemPoolSize", cfg.MemPoolSize)) log.Info("mempool size is not set or wrong, setting default value", zap.Int("MemPoolSize", cfg.MemPoolSize))
} }
validators, err := validatorsFromConfig(cfg)
if err != nil {
return nil, err
}
bc := &Blockchain{ bc := &Blockchain{
config: cfg, config: cfg,
dao: dao.NewSimple(s, cfg.Magic), dao: dao.NewSimple(s, cfg.Magic),
@ -161,6 +167,7 @@ func NewBlockchain(s storage.Store, cfg config.ProtocolConfiguration, log *zap.L
runToExitCh: make(chan struct{}), runToExitCh: make(chan struct{}),
memPool: mempool.NewMemPool(cfg.MemPoolSize), memPool: mempool.NewMemPool(cfg.MemPoolSize),
keyCache: make(map[util.Uint160]map[string]*keys.PublicKey), keyCache: make(map[util.Uint160]map[string]*keys.PublicKey),
sbValidators: validators,
log: log, log: log,
events: make(chan bcEvent), events: make(chan bcEvent),
subCh: make(chan interface{}), subCh: make(chan interface{}),
@ -1235,8 +1242,10 @@ func (bc *Blockchain) PoolTx(t *transaction.Transaction) error {
} }
//GetStandByValidators returns validators from the configuration. //GetStandByValidators returns validators from the configuration.
func (bc *Blockchain) GetStandByValidators() (keys.PublicKeys, error) { func (bc *Blockchain) GetStandByValidators() keys.PublicKeys {
return getValidators(bc.config) res := make(keys.PublicKeys, len(bc.sbValidators))
copy(res, bc.sbValidators)
return res
} }
// GetValidators returns next block validators. // GetValidators returns next block validators.

View file

@ -37,7 +37,7 @@ type Blockchainer interface {
GetNEP5TransferLog(util.Uint160) *state.NEP5TransferLog GetNEP5TransferLog(util.Uint160) *state.NEP5TransferLog
GetNEP5Balances(util.Uint160) *state.NEP5Balances GetNEP5Balances(util.Uint160) *state.NEP5Balances
GetValidators() ([]*keys.PublicKey, error) GetValidators() ([]*keys.PublicKey, error)
GetStandByValidators() (keys.PublicKeys, error) GetStandByValidators() keys.PublicKeys
GetScriptHashesForVerifying(*transaction.Transaction) ([]util.Uint160, error) GetScriptHashesForVerifying(*transaction.Transaction) ([]util.Uint160, error)
GetStorageItem(id int32, key []byte) *state.StorageItem GetStorageItem(id int32, key []byte) *state.StorageItem
GetStorageItems(id int32) (map[string]*state.StorageItem, error) GetStorageItems(id int32) (map[string]*state.StorageItem, error)

View file

@ -48,7 +48,7 @@ func (bc *Blockchain) newBlock(txs ...*transaction.Transaction) *block.Block {
} }
func newBlock(cfg config.ProtocolConfiguration, index uint32, prev util.Uint256, txs ...*transaction.Transaction) *block.Block { func newBlock(cfg config.ProtocolConfiguration, index uint32, prev util.Uint256, txs ...*transaction.Transaction) *block.Block {
validators, _ := getValidators(cfg) validators, _ := validatorsFromConfig(cfg)
vlen := len(validators) vlen := len(validators)
valScript, _ := smartcontract.CreateMultiSigRedeemScript( valScript, _ := smartcontract.CreateMultiSigRedeemScript(
vlen-(vlen-1)/3, vlen-(vlen-1)/3,
@ -399,10 +399,7 @@ func addCosigners(txs ...*transaction.Transaction) {
} }
func signTx(bc *Blockchain, txs ...*transaction.Transaction) error { func signTx(bc *Blockchain, txs ...*transaction.Transaction) error {
validators, err := getValidators(bc.config) validators := bc.GetStandByValidators()
if err != nil {
return errors.Wrap(err, "fail to sign tx")
}
rawScript, err := smartcontract.CreateMultiSigRedeemScript(len(bc.config.StandbyValidators)/2+1, validators) rawScript, err := smartcontract.CreateMultiSigRedeemScript(len(bc.config.StandbyValidators)/2+1, validators)
if err != nil { if err != nil {
return errors.Wrap(err, "fail to sign tx") return errors.Wrap(err, "fail to sign tx")

View file

@ -101,10 +101,7 @@ func (g *GAS) OnPersist(ic *interop.Context) error {
} }
func getStandbyValidatorsHash(ic *interop.Context) (util.Uint160, []*keys.PublicKey, error) { func getStandbyValidatorsHash(ic *interop.Context) (util.Uint160, []*keys.PublicKey, error) {
vs, err := ic.Chain.GetStandByValidators() vs := ic.Chain.GetStandByValidators()
if err != nil {
return util.Uint160{}, nil, err
}
s, err := smartcontract.CreateMultiSigRedeemScript(len(vs)/2+1, vs) s, err := smartcontract.CreateMultiSigRedeemScript(len(vs)/2+1, vs)
if err != nil { if err != nil {
return util.Uint160{}, nil, err return util.Uint160{}, nil, err

View file

@ -384,10 +384,7 @@ func (n *NEO) getRegisteredValidatorsCall(ic *interop.Context, _ []stackitem.Ite
// GetValidatorsInternal returns a list of current validators. // GetValidatorsInternal returns a list of current validators.
func (n *NEO) GetValidatorsInternal(bc blockchainer.Blockchainer, d dao.DAO) (keys.PublicKeys, error) { func (n *NEO) GetValidatorsInternal(bc blockchainer.Blockchainer, d dao.DAO) (keys.PublicKeys, error) {
standByValidators, err := bc.GetStandByValidators() standByValidators := bc.GetStandByValidators()
if err != nil {
return nil, err
}
si := d.GetStorageItem(n.ContractID, validatorsCountKey) si := d.GetStorageItem(n.ContractID, validatorsCountKey)
if si == nil { if si == nil {
return standByValidators, nil return standByValidators, nil

View file

@ -34,7 +34,7 @@ var (
// createGenesisBlock creates a genesis block based on the given configuration. // createGenesisBlock creates a genesis block based on the given configuration.
func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error) { func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error) {
validators, err := getValidators(cfg) validators, err := validatorsFromConfig(cfg)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -91,7 +91,7 @@ func deployNativeContracts(magic netmode.Magic) *transaction.Transaction {
return tx return tx
} }
func getValidators(cfg config.ProtocolConfiguration) ([]*keys.PublicKey, error) { func validatorsFromConfig(cfg config.ProtocolConfiguration) ([]*keys.PublicKey, error) {
validators := make([]*keys.PublicKey, len(cfg.StandbyValidators)) validators := make([]*keys.PublicKey, len(cfg.StandbyValidators))
for i, pubKeyStr := range cfg.StandbyValidators { for i, pubKeyStr := range cfg.StandbyValidators {
pubKey, err := keys.NewPublicKeyFromString(pubKeyStr) pubKey, err := keys.NewPublicKeyFromString(pubKeyStr)

View file

@ -34,7 +34,7 @@ func TestGetConsensusAddressMainNet(t *testing.T) {
cfg, err := config.Load("../../config", netmode.MainNet) cfg, err := config.Load("../../config", netmode.MainNet)
require.NoError(t, err) require.NoError(t, err)
validators, err := getValidators(cfg.ProtocolConfiguration) validators, err := validatorsFromConfig(cfg.ProtocolConfiguration)
require.NoError(t, err) require.NoError(t, err)
script, err := getNextConsensusAddress(validators) script, err := getNextConsensusAddress(validators)

View file

@ -85,7 +85,7 @@ func (chain testChain) GetNEP5Balances(util.Uint160) *state.NEP5Balances {
func (chain testChain) GetValidators() ([]*keys.PublicKey, error) { func (chain testChain) GetValidators() ([]*keys.PublicKey, error) {
panic("TODO") panic("TODO")
} }
func (chain testChain) GetStandByValidators() (keys.PublicKeys, error) { func (chain testChain) GetStandByValidators() keys.PublicKeys {
panic("TODO") panic("TODO")
} }
func (chain testChain) GetEnrollments() ([]state.Validator, error) { func (chain testChain) GetEnrollments() ([]state.Validator, error) {

View file

@ -577,8 +577,7 @@ var rpcTestCases = map[string][]rpcTestCase{
}, },
check: func(t *testing.T, e *executor, validators interface{}) { check: func(t *testing.T, e *executor, validators interface{}) {
var expected []result.Validator var expected []result.Validator
sBValidators, err := e.chain.GetStandByValidators() sBValidators := e.chain.GetStandByValidators()
require.NoError(t, err)
for _, sbValidator := range sBValidators { for _, sbValidator := range sBValidators {
expected = append(expected, result.Validator{ expected = append(expected, result.Validator{
PublicKey: *sbValidator, PublicKey: *sbValidator,