mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-23 13:41:37 +00:00
native: cache all roles in Designate
This commit is contained in:
parent
9a99054e6b
commit
db4e7558e0
2 changed files with 61 additions and 26 deletions
|
@ -30,6 +30,8 @@ type Designate struct {
|
||||||
|
|
||||||
rolesChangedFlag atomic.Value
|
rolesChangedFlag atomic.Value
|
||||||
oracles atomic.Value
|
oracles atomic.Value
|
||||||
|
stateVals atomic.Value
|
||||||
|
notaries atomic.Value
|
||||||
|
|
||||||
// p2pSigExtensionsEnabled defines whether the P2P signature extensions logic is relevant.
|
// p2pSigExtensionsEnabled defines whether the P2P signature extensions logic is relevant.
|
||||||
p2pSigExtensionsEnabled bool
|
p2pSigExtensionsEnabled bool
|
||||||
|
@ -37,7 +39,7 @@ type Designate struct {
|
||||||
OracleService atomic.Value
|
OracleService atomic.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
type oraclesData struct {
|
type roleData struct {
|
||||||
nodes keys.PublicKeys
|
nodes keys.PublicKeys
|
||||||
addr util.Uint160
|
addr util.Uint160
|
||||||
height uint32
|
height uint32
|
||||||
|
@ -109,20 +111,18 @@ func (s *Designate) PostPersist(ic *interop.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeKeys, height, err := s.GetDesignatedByRole(ic.DAO, RoleOracle, math.MaxUint32)
|
if err := s.updateCachedRoleData(&s.oracles, ic.DAO, RoleOracle); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := s.updateCachedRoleData(&s.stateVals, ic.DAO, RoleStateValidator); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if s.p2pSigExtensionsEnabled {
|
||||||
|
if err := s.updateCachedRoleData(&s.notaries, ic.DAO, RoleP2PNotary); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
od := &oraclesData{
|
|
||||||
nodes: nodeKeys,
|
|
||||||
addr: oracleHashFromNodes(nodeKeys),
|
|
||||||
height: height,
|
|
||||||
}
|
|
||||||
s.oracles.Store(od)
|
|
||||||
if orc, _ := s.OracleService.Load().(services.Oracle); orc != nil {
|
|
||||||
orc.UpdateOracleNodes(od.nodes.Copy())
|
|
||||||
}
|
|
||||||
s.rolesChangedFlag.Store(false)
|
s.rolesChangedFlag.Store(false)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -157,7 +157,7 @@ func (s *Designate) rolesChanged() bool {
|
||||||
return rc == nil || rc.(bool)
|
return rc == nil || rc.(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
func oracleHashFromNodes(nodes keys.PublicKeys) util.Uint160 {
|
func majorityHashFromNodes(nodes keys.PublicKeys) util.Uint160 {
|
||||||
if len(nodes) == 0 {
|
if len(nodes) == 0 {
|
||||||
return util.Uint160{}
|
return util.Uint160{}
|
||||||
}
|
}
|
||||||
|
@ -165,15 +165,47 @@ func oracleHashFromNodes(nodes keys.PublicKeys) util.Uint160 {
|
||||||
return hash.Hash160(script)
|
return hash.Hash160(script)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Designate) updateCachedRoleData(v *atomic.Value, d dao.DAO, r Role) error {
|
||||||
|
nodeKeys, height, err := s.GetDesignatedByRole(d, r, math.MaxUint32)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
v.Store(&roleData{
|
||||||
|
nodes: nodeKeys,
|
||||||
|
addr: majorityHashFromNodes(nodeKeys),
|
||||||
|
height: height,
|
||||||
|
})
|
||||||
|
if r == RoleOracle {
|
||||||
|
if orc, _ := s.OracleService.Load().(services.Oracle); orc != nil {
|
||||||
|
orc.UpdateOracleNodes(nodeKeys.Copy())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Designate) getCachedRoleData(r Role) *roleData {
|
||||||
|
var val interface{}
|
||||||
|
switch r {
|
||||||
|
case RoleOracle:
|
||||||
|
val = s.oracles.Load()
|
||||||
|
case RoleStateValidator:
|
||||||
|
val = s.stateVals.Load()
|
||||||
|
case RoleP2PNotary:
|
||||||
|
val = s.notaries.Load()
|
||||||
|
}
|
||||||
|
if val != nil {
|
||||||
|
return val.(*roleData)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Designate) getLastDesignatedHash(d dao.DAO, r Role) (util.Uint160, error) {
|
func (s *Designate) getLastDesignatedHash(d dao.DAO, r Role) (util.Uint160, error) {
|
||||||
if !s.isValidRole(r) {
|
if !s.isValidRole(r) {
|
||||||
return util.Uint160{}, ErrInvalidRole
|
return util.Uint160{}, ErrInvalidRole
|
||||||
}
|
}
|
||||||
if r == RoleOracle && !s.rolesChanged() {
|
if !s.rolesChanged() {
|
||||||
odVal := s.oracles.Load()
|
if val := s.getCachedRoleData(r); val != nil {
|
||||||
if odVal != nil {
|
return val.addr, nil
|
||||||
od := odVal.(*oraclesData)
|
|
||||||
return od.addr, nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nodes, _, err := s.GetDesignatedByRole(d, r, math.MaxUint32)
|
nodes, _, err := s.GetDesignatedByRole(d, r, math.MaxUint32)
|
||||||
|
@ -181,7 +213,7 @@ func (s *Designate) getLastDesignatedHash(d dao.DAO, r Role) (util.Uint160, erro
|
||||||
return util.Uint160{}, err
|
return util.Uint160{}, err
|
||||||
}
|
}
|
||||||
// We only have hashing defined for oracles now.
|
// We only have hashing defined for oracles now.
|
||||||
return oracleHashFromNodes(nodes), nil
|
return majorityHashFromNodes(nodes), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDesignatedByRole returns nodes for role r.
|
// GetDesignatedByRole returns nodes for role r.
|
||||||
|
@ -189,13 +221,9 @@ func (s *Designate) GetDesignatedByRole(d dao.DAO, r Role, index uint32) (keys.P
|
||||||
if !s.isValidRole(r) {
|
if !s.isValidRole(r) {
|
||||||
return nil, 0, ErrInvalidRole
|
return nil, 0, ErrInvalidRole
|
||||||
}
|
}
|
||||||
if r == RoleOracle && !s.rolesChanged() {
|
if !s.rolesChanged() {
|
||||||
odVal := s.oracles.Load()
|
if val := s.getCachedRoleData(r); val != nil && val.height <= index {
|
||||||
if odVal != nil {
|
return val.nodes.Copy(), val.height, nil
|
||||||
od := odVal.(*oraclesData)
|
|
||||||
if od.height <= index {
|
|
||||||
return od.nodes, od.height, nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
kvs, err := d.GetStorageItemsWithPrefix(s.ContractID, []byte{byte(r)})
|
kvs, err := d.GetStorageItemsWithPrefix(s.ContractID, []byte{byte(r)})
|
||||||
|
|
|
@ -93,6 +93,13 @@ func TestDesignate_DesignateAsRoleTx(t *testing.T) {
|
||||||
bc.getNodesByRole(t, false, native.RoleOracle, 100500, 0)
|
bc.getNodesByRole(t, false, native.RoleOracle, 100500, 0)
|
||||||
bc.getNodesByRole(t, true, native.RoleOracle, 0, 0) // returns an empty list
|
bc.getNodesByRole(t, true, native.RoleOracle, 0, 0) // returns an empty list
|
||||||
bc.getNodesByRole(t, true, native.RoleOracle, index, 1) // returns pubs
|
bc.getNodesByRole(t, true, native.RoleOracle, index, 1) // returns pubs
|
||||||
|
|
||||||
|
priv1, err := keys.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
pubs = keys.PublicKeys{priv1.PublicKey()}
|
||||||
|
bc.setNodesByRole(t, true, native.RoleStateValidator, pubs)
|
||||||
|
bc.getNodesByRole(t, true, native.RoleStateValidator, bc.BlockHeight()+1, 1)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDesignate_DesignateAsRole(t *testing.T) {
|
func TestDesignate_DesignateAsRole(t *testing.T) {
|
||||||
|
|
Loading…
Reference in a new issue