forked from TrueCloudLab/neoneo-go
core: set native script and hash in SetOracle
This commit is contained in:
parent
f9f1fe03b2
commit
61ce4a7f79
5 changed files with 42 additions and 16 deletions
|
@ -197,7 +197,14 @@ func NewBlockchain(s storage.Store, cfg config.ProtocolConfiguration, log *zap.L
|
||||||
// SetOracle sets oracle module. It doesn't protected by mutex and
|
// SetOracle sets oracle module. It doesn't protected by mutex and
|
||||||
// must be called before `bc.Run()` to avoid data race.
|
// must be called before `bc.Run()` to avoid data race.
|
||||||
func (bc *Blockchain) SetOracle(mod services.Oracle) {
|
func (bc *Blockchain) SetOracle(mod services.Oracle) {
|
||||||
bc.contracts.Oracle.Module.Store(mod)
|
orc := bc.contracts.Oracle
|
||||||
|
md, ok := orc.GetMethod(manifest.MethodVerify, -1)
|
||||||
|
if !ok {
|
||||||
|
panic(fmt.Errorf("%s method not found", manifest.MethodVerify))
|
||||||
|
}
|
||||||
|
mod.UpdateNativeContract(orc.NEF.Script, orc.GetOracleResponseScript(),
|
||||||
|
orc.Hash, md.MD.Offset)
|
||||||
|
orc.Module.Store(mod)
|
||||||
bc.contracts.Designate.OracleService.Store(mod)
|
bc.contracts.Designate.OracleService.Store(mod)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package services
|
||||||
import (
|
import (
|
||||||
"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/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Oracle specifies oracle service interface.
|
// Oracle specifies oracle service interface.
|
||||||
|
@ -13,6 +14,8 @@ type Oracle interface {
|
||||||
RemoveRequests([]uint64)
|
RemoveRequests([]uint64)
|
||||||
// UpdateOracleNodes updates oracle nodes.
|
// UpdateOracleNodes updates oracle nodes.
|
||||||
UpdateOracleNodes(keys.PublicKeys)
|
UpdateOracleNodes(keys.PublicKeys)
|
||||||
|
// UpdateNativeContract updates oracle contract native script and hash.
|
||||||
|
UpdateNativeContract([]byte, []byte, util.Uint160, int)
|
||||||
// Run runs oracle module. Must be invoked in a separate goroutine.
|
// Run runs oracle module. Must be invoked in a separate goroutine.
|
||||||
Run()
|
Run()
|
||||||
// Shutdown shutdowns oracle module.
|
// Shutdown shutdowns oracle module.
|
||||||
|
|
|
@ -30,7 +30,6 @@ import (
|
||||||
const oracleModulePath = "../services/oracle/"
|
const oracleModulePath = "../services/oracle/"
|
||||||
|
|
||||||
func getOracleConfig(t *testing.T, bc *Blockchain, w, pass string) oracle.Config {
|
func getOracleConfig(t *testing.T, bc *Blockchain, w, pass string) oracle.Config {
|
||||||
m := bc.contracts.Oracle.Manifest.ABI.GetMethod(manifest.MethodVerify, 0)
|
|
||||||
return oracle.Config{
|
return oracle.Config{
|
||||||
Log: zaptest.NewLogger(t),
|
Log: zaptest.NewLogger(t),
|
||||||
Network: netmode.UnitTestNet,
|
Network: netmode.UnitTestNet,
|
||||||
|
@ -41,12 +40,8 @@ func getOracleConfig(t *testing.T, bc *Blockchain, w, pass string) oracle.Config
|
||||||
Password: pass,
|
Password: pass,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Chain: bc,
|
Chain: bc,
|
||||||
Client: newDefaultHTTPClient(),
|
Client: newDefaultHTTPClient(),
|
||||||
OracleScript: bc.contracts.Oracle.NEF.Script,
|
|
||||||
OracleResponse: bc.contracts.Oracle.GetOracleResponseScript(),
|
|
||||||
OracleHash: bc.contracts.Oracle.Hash,
|
|
||||||
VerifyOffset: m.Offset,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,6 +95,7 @@ func TestCreateResponseTx(t *testing.T) {
|
||||||
}
|
}
|
||||||
require.NoError(t, bc.contracts.Oracle.PutRequestInternal(1, req, bc.dao))
|
require.NoError(t, bc.contracts.Oracle.PutRequestInternal(1, req, bc.dao))
|
||||||
orc.UpdateOracleNodes(keys.PublicKeys{acc.PrivateKey().PublicKey()})
|
orc.UpdateOracleNodes(keys.PublicKeys{acc.PrivateKey().PublicKey()})
|
||||||
|
bc.SetOracle(orc)
|
||||||
tx, err := orc.CreateResponseTx(int64(req.GasForResponse), 1, resp)
|
tx, err := orc.CreateResponseTx(int64(req.GasForResponse), 1, resp)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 167, tx.Size())
|
assert.Equal(t, 167, tx.Size())
|
||||||
|
@ -130,6 +126,12 @@ func TestOracle(t *testing.T) {
|
||||||
orc1.UpdateOracleNodes(oracleNodes.Copy())
|
orc1.UpdateOracleNodes(oracleNodes.Copy())
|
||||||
orc2.UpdateOracleNodes(oracleNodes.Copy())
|
orc2.UpdateOracleNodes(oracleNodes.Copy())
|
||||||
|
|
||||||
|
orcNative := bc.contracts.Oracle
|
||||||
|
md, ok := orcNative.GetMethod(manifest.MethodVerify, -1)
|
||||||
|
require.True(t, ok)
|
||||||
|
orc1.UpdateNativeContract(orcNative.NEF.Script, orcNative.GetOracleResponseScript(), orcNative.Hash, md.MD.Offset)
|
||||||
|
orc2.UpdateNativeContract(orcNative.NEF.Script, orcNative.GetOracleResponseScript(), orcNative.Hash, md.MD.Offset)
|
||||||
|
|
||||||
cs := getOracleContractState(bc.contracts.Oracle.Hash)
|
cs := getOracleContractState(bc.contracts.Oracle.Hash)
|
||||||
require.NoError(t, bc.contracts.Management.PutContractState(bc.dao, cs))
|
require.NoError(t, bc.contracts.Management.PutContractState(bc.dao, cs))
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,12 @@ type (
|
||||||
Oracle struct {
|
Oracle struct {
|
||||||
Config
|
Config
|
||||||
|
|
||||||
|
// This fields are readonly thus not protected by mutex.
|
||||||
|
oracleHash util.Uint160
|
||||||
|
oracleResponse []byte
|
||||||
|
oracleScript []byte
|
||||||
|
verifyOffset int
|
||||||
|
|
||||||
// mtx protects setting callbacks.
|
// mtx protects setting callbacks.
|
||||||
mtx sync.RWMutex
|
mtx sync.RWMutex
|
||||||
|
|
||||||
|
@ -56,10 +62,6 @@ type (
|
||||||
ResponseHandler Broadcaster
|
ResponseHandler Broadcaster
|
||||||
OnTransaction TxCallback
|
OnTransaction TxCallback
|
||||||
URIValidator URIValidator
|
URIValidator URIValidator
|
||||||
OracleScript []byte
|
|
||||||
OracleResponse []byte
|
|
||||||
VerifyOffset int
|
|
||||||
OracleHash util.Uint160
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTPClient is an interface capable of doing oracle requests.
|
// HTTPClient is an interface capable of doing oracle requests.
|
||||||
|
@ -203,6 +205,18 @@ func (o *Oracle) Run() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateNativeContract updates native oracle contract info for tx verification.
|
||||||
|
func (o *Oracle) UpdateNativeContract(script, resp []byte, h util.Uint160, verifyOffset int) {
|
||||||
|
o.oracleScript = make([]byte, len(script))
|
||||||
|
copy(o.oracleScript, script)
|
||||||
|
|
||||||
|
o.oracleResponse = make([]byte, len(resp))
|
||||||
|
copy(o.oracleResponse, resp)
|
||||||
|
|
||||||
|
o.oracleHash = h
|
||||||
|
o.verifyOffset = verifyOffset
|
||||||
|
}
|
||||||
|
|
||||||
func (o *Oracle) getOnTransaction() TxCallback {
|
func (o *Oracle) getOnTransaction() TxCallback {
|
||||||
o.mtx.RLock()
|
o.mtx.RLock()
|
||||||
defer o.mtx.RUnlock()
|
defer o.mtx.RUnlock()
|
||||||
|
|
|
@ -82,7 +82,7 @@ func readResponse(rc gio.ReadCloser, limit int) ([]byte, error) {
|
||||||
|
|
||||||
// CreateResponseTx creates unsigned oracle response transaction.
|
// CreateResponseTx creates unsigned oracle response transaction.
|
||||||
func (o *Oracle) CreateResponseTx(gasForResponse int64, height uint32, resp *transaction.OracleResponse) (*transaction.Transaction, error) {
|
func (o *Oracle) CreateResponseTx(gasForResponse int64, height uint32, resp *transaction.OracleResponse) (*transaction.Transaction, error) {
|
||||||
tx := transaction.New(o.Network, o.OracleResponse, 0)
|
tx := transaction.New(o.Network, o.oracleResponse, 0)
|
||||||
tx.Nonce = uint32(resp.ID)
|
tx.Nonce = uint32(resp.ID)
|
||||||
tx.ValidUntilBlock = height + transaction.MaxValidUntilBlockIncrement
|
tx.ValidUntilBlock = height + transaction.MaxValidUntilBlockIncrement
|
||||||
tx.Attributes = []transaction.Attribute{{
|
tx.Attributes = []transaction.Attribute{{
|
||||||
|
@ -93,7 +93,7 @@ func (o *Oracle) CreateResponseTx(gasForResponse int64, height uint32, resp *tra
|
||||||
oracleSignContract := o.getOracleSignContract()
|
oracleSignContract := o.getOracleSignContract()
|
||||||
tx.Signers = []transaction.Signer{
|
tx.Signers = []transaction.Signer{
|
||||||
{
|
{
|
||||||
Account: o.OracleHash,
|
Account: o.oracleHash,
|
||||||
Scopes: transaction.None,
|
Scopes: transaction.None,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -136,8 +136,8 @@ func (o *Oracle) CreateResponseTx(gasForResponse int64, height uint32, resp *tra
|
||||||
func (o *Oracle) testVerify(tx *transaction.Transaction) (int64, bool) {
|
func (o *Oracle) testVerify(tx *transaction.Transaction) (int64, bool) {
|
||||||
v := o.Chain.GetTestVM(trigger.Verification, tx, nil)
|
v := o.Chain.GetTestVM(trigger.Verification, tx, nil)
|
||||||
v.GasLimit = o.Chain.GetPolicer().GetMaxVerificationGAS()
|
v.GasLimit = o.Chain.GetPolicer().GetMaxVerificationGAS()
|
||||||
v.LoadScriptWithHash(o.OracleScript, o.OracleHash, callflag.ReadOnly)
|
v.LoadScriptWithHash(o.oracleScript, o.oracleHash, callflag.ReadOnly)
|
||||||
v.Jump(v.Context(), o.VerifyOffset)
|
v.Jump(v.Context(), o.verifyOffset)
|
||||||
|
|
||||||
ok := isVerifyOk(v)
|
ok := isVerifyOk(v)
|
||||||
return v.GasConsumed(), ok
|
return v.GasConsumed(), ok
|
||||||
|
|
Loading…
Reference in a new issue