forked from TrueCloudLab/neoneo-go
native: cache oracle nodes
This commit is contained in:
parent
141d6e325f
commit
bd1790bddf
3 changed files with 32 additions and 16 deletions
|
@ -650,6 +650,7 @@ func (bc *Blockchain) storeBlock(block *block.Block, txpool *mempool.Pool) error
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
bc.contracts.Policy.OnPersistEnd(bc.dao)
|
bc.contracts.Policy.OnPersistEnd(bc.dao)
|
||||||
|
bc.contracts.Oracle.OnPersistEnd(bc.dao)
|
||||||
bc.dao.MPT.Flush()
|
bc.dao.MPT.Flush()
|
||||||
// Every persist cycle we also compact our in-memory MPT.
|
// Every persist cycle we also compact our in-memory MPT.
|
||||||
persistedHeight := atomic.LoadUint32(&bc.persistedHeight)
|
persistedHeight := atomic.LoadUint32(&bc.persistedHeight)
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sort"
|
"sort"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||||
|
@ -30,6 +31,11 @@ type Oracle struct {
|
||||||
interop.ContractMD
|
interop.ContractMD
|
||||||
GAS *GAS
|
GAS *GAS
|
||||||
NEO *NEO
|
NEO *NEO
|
||||||
|
|
||||||
|
// nodesChanged is true if `SetOracleNodes` was called.
|
||||||
|
nodesChanged atomic.Value
|
||||||
|
// nodes contains cached list of oracle nodes.
|
||||||
|
nodes atomic.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -165,10 +171,7 @@ func (o *Oracle) PostPersist(ic *interop.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if nodes == nil {
|
if nodes == nil {
|
||||||
nodes, err = o.GetOracleNodes(ic.DAO)
|
nodes = o.GetOracleNodes()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
reward = make([]big.Int, len(nodes))
|
reward = make([]big.Int, len(nodes))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,6 +197,8 @@ func (o *Oracle) Initialize(ic *interop.Context) error {
|
||||||
if err := ic.DAO.PutStorageItem(o.ContractID, prefixNodeList, si); err != nil {
|
if err := ic.DAO.PutStorageItem(o.ContractID, prefixNodeList, si); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
o.nodes.Store(keys.PublicKeys(nil))
|
||||||
|
o.nodesChanged.Store(false)
|
||||||
si = &state.StorageItem{Value: make([]byte, 8)} // uint64(0) LE
|
si = &state.StorageItem{Value: make([]byte, 8)} // uint64(0) LE
|
||||||
return ic.DAO.PutStorageItem(o.ContractID, prefixRequestID, si)
|
return ic.DAO.PutStorageItem(o.ContractID, prefixRequestID, si)
|
||||||
}
|
}
|
||||||
|
@ -324,17 +329,13 @@ func (o *Oracle) RequestInternal(ic *interop.Context, url, filter, cb string, us
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Oracle) getOracleNodes(ic *interop.Context, _ []stackitem.Item) stackitem.Item {
|
func (o *Oracle) getOracleNodes(ic *interop.Context, _ []stackitem.Item) stackitem.Item {
|
||||||
pubs, err := o.GetOracleNodes(ic.DAO)
|
pubs := o.GetOracleNodes()
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return pubsToArray(pubs)
|
return pubsToArray(pubs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOracleNodes returns public keys of oracle nodes.
|
// GetOracleNodes returns public keys of oracle nodes.
|
||||||
func (o *Oracle) GetOracleNodes(d dao.DAO) (keys.PublicKeys, error) {
|
func (o *Oracle) GetOracleNodes() keys.PublicKeys {
|
||||||
ns := new(NodeList)
|
return o.nodes.Load().(keys.PublicKeys).Copy()
|
||||||
return keys.PublicKeys(*ns), o.getSerializableFromDAO(d, prefixNodeList, ns)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Oracle) setOracleNodes(ic *interop.Context, _ []stackitem.Item) stackitem.Item {
|
func (o *Oracle) setOracleNodes(ic *interop.Context, _ []stackitem.Item) stackitem.Item {
|
||||||
|
@ -357,6 +358,7 @@ func (o *Oracle) SetOracleNodes(ic *interop.Context, pubs keys.PublicKeys) error
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Sort(pubs)
|
sort.Sort(pubs)
|
||||||
|
o.nodesChanged.Store(true)
|
||||||
si := &state.StorageItem{Value: NodeList(pubs).Bytes()}
|
si := &state.StorageItem{Value: NodeList(pubs).Bytes()}
|
||||||
return ic.DAO.PutStorageItem(o.ContractID, prefixNodeList, si)
|
return ic.DAO.PutStorageItem(o.ContractID, prefixNodeList, si)
|
||||||
}
|
}
|
||||||
|
@ -410,3 +412,16 @@ func (o *Oracle) getSerializableFromDAO(d dao.DAO, key []byte, item io.Serializa
|
||||||
item.DecodeBinary(r)
|
item.DecodeBinary(r)
|
||||||
return r.Err
|
return r.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OnPersistEnd updates cached Oracle values if they've been changed
|
||||||
|
func (o *Oracle) OnPersistEnd(d dao.DAO) {
|
||||||
|
if !o.nodesChanged.Load().(bool) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ns := new(NodeList)
|
||||||
|
_ = o.getSerializableFromDAO(d, prefixNodeList, ns)
|
||||||
|
o.nodes.Store(keys.PublicKeys(*ns))
|
||||||
|
o.nodesChanged.Store(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -141,6 +141,7 @@ func TestOracle_Request(t *testing.T) {
|
||||||
ic := bc.newInteropContext(trigger.Application, bc.dao, nil, tx)
|
ic := bc.newInteropContext(trigger.Application, bc.dao, nil, tx)
|
||||||
err = orc.SetOracleNodes(ic, keys.PublicKeys{pub})
|
err = orc.SetOracleNodes(ic, keys.PublicKeys{pub})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
orc.OnPersistEnd(ic.DAO)
|
||||||
|
|
||||||
tx = transaction.New(netmode.UnitTestNet, native.GetOracleResponseScript(), 0)
|
tx = transaction.New(netmode.UnitTestNet, native.GetOracleResponseScript(), 0)
|
||||||
ic.Tx = tx
|
ic.Tx = tx
|
||||||
|
@ -223,11 +224,10 @@ func TestOracle_SetOracleNodes(t *testing.T) {
|
||||||
ic := bc.newInteropContext(trigger.System, bc.dao, nil, tx)
|
ic := bc.newInteropContext(trigger.System, bc.dao, nil, tx)
|
||||||
ic.VM = vm.New()
|
ic.VM = vm.New()
|
||||||
|
|
||||||
pubs, err := orc.GetOracleNodes(ic.DAO)
|
pubs := orc.GetOracleNodes()
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, 0, len(pubs))
|
require.Equal(t, 0, len(pubs))
|
||||||
|
|
||||||
err = orc.SetOracleNodes(ic, keys.PublicKeys{})
|
err := orc.SetOracleNodes(ic, keys.PublicKeys{})
|
||||||
require.True(t, errors.Is(err, native.ErrEmptyNodeList), "got: %v", err)
|
require.True(t, errors.Is(err, native.ErrEmptyNodeList), "got: %v", err)
|
||||||
|
|
||||||
priv, err := keys.NewPrivateKey()
|
priv, err := keys.NewPrivateKey()
|
||||||
|
@ -239,8 +239,8 @@ func TestOracle_SetOracleNodes(t *testing.T) {
|
||||||
|
|
||||||
setSigner(tx, testchain.CommitteeScriptHash())
|
setSigner(tx, testchain.CommitteeScriptHash())
|
||||||
require.NoError(t, orc.SetOracleNodes(ic, keys.PublicKeys{pub}))
|
require.NoError(t, orc.SetOracleNodes(ic, keys.PublicKeys{pub}))
|
||||||
|
orc.OnPersistEnd(ic.DAO)
|
||||||
|
|
||||||
pubs, err = orc.GetOracleNodes(ic.DAO)
|
pubs = orc.GetOracleNodes()
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, keys.PublicKeys{pub}, pubs)
|
require.Equal(t, keys.PublicKeys{pub}, pubs)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue