core, services: fix Designation-dependant service initialisation
Initialise services dependant on roles designation based on N+1 block so that Genesis roles extension work properly. There's not much sence to fetch node roles information for the latest persisted block because Designation contract itself makes designated nodes responsible since the next subsequent block. A part of #3228. Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
This commit is contained in:
parent
4216efbe6c
commit
11ec0db350
5 changed files with 76 additions and 2 deletions
|
@ -332,6 +332,16 @@ func NewBlockchain(s storage.Store, cfg config.Blockchain, log *zap.Logger) (*Bl
|
||||||
return bc, nil
|
return bc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDesignatedByRole returns a set of designated public keys for the given role
|
||||||
|
// relevant for the next block.
|
||||||
|
func (bc *Blockchain) GetDesignatedByRole(r noderoles.Role) (keys.PublicKeys, uint32, error) {
|
||||||
|
// Retrieve designated nodes starting from the next block, because the current
|
||||||
|
// block is already stored, thus, dependant services can't use PostPersist callback
|
||||||
|
// to fetch relevant information at their start.
|
||||||
|
res, h, err := bc.contracts.Designate.GetDesignatedByRole(bc.dao, r, bc.BlockHeight()+1)
|
||||||
|
return res, h, err
|
||||||
|
}
|
||||||
|
|
||||||
// SetOracle sets oracle module. It can safely be called on the running blockchain.
|
// SetOracle sets oracle module. It can safely be called on the running blockchain.
|
||||||
// To unregister Oracle service use SetOracle(nil).
|
// To unregister Oracle service use SetOracle(nil).
|
||||||
func (bc *Blockchain) SetOracle(mod native.OracleService) {
|
func (bc *Blockchain) SetOracle(mod native.OracleService) {
|
||||||
|
@ -343,7 +353,7 @@ func (bc *Blockchain) SetOracle(mod native.OracleService) {
|
||||||
}
|
}
|
||||||
mod.UpdateNativeContract(orc.NEF.Script, orc.GetOracleResponseScript(),
|
mod.UpdateNativeContract(orc.NEF.Script, orc.GetOracleResponseScript(),
|
||||||
orc.Hash, md.MD.Offset)
|
orc.Hash, md.MD.Offset)
|
||||||
keys, _, err := bc.contracts.Designate.GetDesignatedByRole(bc.dao, noderoles.Oracle, bc.BlockHeight())
|
keys, _, err := bc.GetDesignatedByRole(noderoles.Oracle)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
bc.log.Error("failed to get oracle key list")
|
bc.log.Error("failed to get oracle key list")
|
||||||
return
|
return
|
||||||
|
@ -364,7 +374,7 @@ func (bc *Blockchain) SetOracle(mod native.OracleService) {
|
||||||
// To unregister Notary service use SetNotary(nil).
|
// To unregister Notary service use SetNotary(nil).
|
||||||
func (bc *Blockchain) SetNotary(mod native.NotaryService) {
|
func (bc *Blockchain) SetNotary(mod native.NotaryService) {
|
||||||
if mod != nil {
|
if mod != nil {
|
||||||
keys, _, err := bc.contracts.Designate.GetDesignatedByRole(bc.dao, noderoles.P2PNotary, bc.BlockHeight())
|
keys, _, err := bc.GetDesignatedByRole(noderoles.P2PNotary)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
bc.log.Error("failed to get notary key list")
|
bc.log.Error("failed to get notary key list")
|
||||||
return
|
return
|
||||||
|
|
|
@ -747,3 +747,28 @@ func TestNotary(t *testing.T) {
|
||||||
}, 3*time.Second, 100*time.Millisecond)
|
}, 3*time.Second, 100*time.Millisecond)
|
||||||
checkFallbackTxs(t, requests, false)
|
checkFallbackTxs(t, requests, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNotary_GenesisRoles(t *testing.T) {
|
||||||
|
const (
|
||||||
|
notaryPath = "./testdata/notary1.json"
|
||||||
|
notaryPass = "one"
|
||||||
|
)
|
||||||
|
|
||||||
|
w, err := wallet.NewWalletFromFile(notaryPath)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, w.Accounts[0].Decrypt(notaryPass, w.Scrypt))
|
||||||
|
acc := w.Accounts[0]
|
||||||
|
|
||||||
|
bc, _, _ := chain.NewMultiWithCustomConfig(t, func(c *config.Blockchain) {
|
||||||
|
c.P2PSigExtensions = true
|
||||||
|
c.Genesis.Roles = map[noderoles.Role]keys.PublicKeys{
|
||||||
|
noderoles.P2PNotary: {acc.PublicKey()},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
_, ntr, _ := getTestNotary(t, bc, "./testdata/notary1.json", "one", func(tx *transaction.Transaction) error { return nil })
|
||||||
|
require.False(t, ntr.IsAuthorized())
|
||||||
|
|
||||||
|
bc.SetNotary(ntr)
|
||||||
|
require.True(t, ntr.IsAuthorized())
|
||||||
|
}
|
||||||
|
|
|
@ -230,6 +230,13 @@ func (n *Notary) Shutdown() {
|
||||||
n.wallet.Close()
|
n.wallet.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsAuthorized returns whether Notary service currently is authorized to collect
|
||||||
|
// signatures. It returnes true iff designated Notary node's account provided to
|
||||||
|
// the Notary service in decrypted state.
|
||||||
|
func (n *Notary) IsAuthorized() bool {
|
||||||
|
return n.getAccount() != nil
|
||||||
|
}
|
||||||
|
|
||||||
// OnNewRequest is a callback method which is called after a new notary request is added to the notary request pool.
|
// OnNewRequest is a callback method which is called after a new notary request is added to the notary request pool.
|
||||||
func (n *Notary) OnNewRequest(payload *payload.P2PNotaryRequest) {
|
func (n *Notary) OnNewRequest(payload *payload.P2PNotaryRequest) {
|
||||||
if !n.started.Load() {
|
if !n.started.Load() {
|
||||||
|
|
|
@ -206,6 +206,13 @@ func (o *Oracle) Start() {
|
||||||
go o.start()
|
go o.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsAuthorized returns whether Oracle service currently is authorized to collect
|
||||||
|
// signatures. It returns true iff designated Oracle node's account provided to
|
||||||
|
// the Oracle service in decrypted state.
|
||||||
|
func (o *Oracle) IsAuthorized() bool {
|
||||||
|
return o.getAccount() != nil
|
||||||
|
}
|
||||||
|
|
||||||
func (o *Oracle) start() {
|
func (o *Oracle) start() {
|
||||||
o.requestMap <- o.pending // Guaranteed to not block, only AddRequests sends to it.
|
o.requestMap <- o.pending // Guaranteed to not block, only AddRequests sends to it.
|
||||||
o.pending = nil
|
o.pending = nil
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core"
|
"github.com/nspcc-dev/neo-go/pkg/core"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
@ -339,6 +340,30 @@ func TestOracle(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestOracle_GenesisRole(t *testing.T) {
|
||||||
|
const (
|
||||||
|
oraclePath = "./testdata/oracle1.json"
|
||||||
|
oraclePass = "one"
|
||||||
|
)
|
||||||
|
w, err := wallet.NewWalletFromFile(oraclePath)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, w.Accounts[0].Decrypt(oraclePass, w.Scrypt))
|
||||||
|
acc := w.Accounts[0]
|
||||||
|
|
||||||
|
bc, _, _ := chain.NewMultiWithCustomConfig(t, func(c *config.Blockchain) {
|
||||||
|
c.Genesis.Roles = map[noderoles.Role]keys.PublicKeys{
|
||||||
|
noderoles.Oracle: {acc.PublicKey()},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
orc, err := oracle.NewOracle(getOracleConfig(t, bc, "./testdata/oracle1.json", "one", nil))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.False(t, orc.IsAuthorized())
|
||||||
|
|
||||||
|
bc.SetOracle(orc)
|
||||||
|
require.True(t, orc.IsAuthorized())
|
||||||
|
}
|
||||||
|
|
||||||
func TestOracleFull(t *testing.T) {
|
func TestOracleFull(t *testing.T) {
|
||||||
bc, validator, committee := chain.NewMultiWithCustomConfigAndStore(t, nil, nil, false)
|
bc, validator, committee := chain.NewMultiWithCustomConfigAndStore(t, nil, nil, false)
|
||||||
e := neotest.NewExecutor(t, bc, validator, committee)
|
e := neotest.NewExecutor(t, bc, validator, committee)
|
||||||
|
|
Loading…
Reference in a new issue