Merge pull request #2279 from nspcc-dev/minor-fixes

services: fix Oracle response creation algorithm
This commit is contained in:
Roman Khimov 2021-11-30 18:15:50 +03:00 committed by GitHub
commit c663d3f39f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 5 deletions

View file

@ -58,14 +58,14 @@ func signStoredTransaction(ctx *cli.Context) error {
} }
if out := ctx.String("out"); out != "" { if out := ctx.String("out"); out != "" {
if err := paramcontext.Save(c, out); err != nil { if err := paramcontext.Save(c, out); err != nil {
return cli.NewExitError(err, 1) return cli.NewExitError(fmt.Errorf("failed to dump resulting transaction: %w", err), 1)
} }
} }
if len(ctx.String(options.RPCEndpointFlag)) != 0 { if len(ctx.String(options.RPCEndpointFlag)) != 0 {
for i := range tx.Signers { for i := range tx.Signers {
w, err := c.GetWitness(tx.Signers[i].Account) w, err := c.GetWitness(tx.Signers[i].Account)
if err != nil { if err != nil {
return cli.NewExitError(err, 1) return cli.NewExitError(fmt.Errorf("failed to construct witness for signer #%d: %w", i, err), 1)
} }
tx.Scripts = append(tx.Scripts, *w) tx.Scripts = append(tx.Scripts, *w)
} }
@ -76,11 +76,11 @@ func signStoredTransaction(ctx *cli.Context) error {
var err error // `GetRPCClient` returns specialized type. var err error // `GetRPCClient` returns specialized type.
c, err := options.GetRPCClient(gctx, ctx) c, err := options.GetRPCClient(gctx, ctx)
if err != nil { if err != nil {
return cli.NewExitError(err, 1) return cli.NewExitError(fmt.Errorf("failed to create RPC client: %w", err), 1)
} }
res, err := c.SendRawTransaction(tx) res, err := c.SendRawTransaction(tx)
if err != nil { if err != nil {
return cli.NewExitError(err, 1) return cli.NewExitError(fmt.Errorf("failed to submit transaction to RPC node: %w", err), 1)
} }
fmt.Fprintln(ctx.App.Writer, res.StringLE()) fmt.Fprintln(ctx.App.Writer, res.StringLE())
return nil return nil

View file

@ -168,6 +168,25 @@ func TestOracle(t *testing.T) {
checkEmitTx := func(t *testing.T, ch chan *transaction.Transaction) { checkEmitTx := func(t *testing.T, ch chan *transaction.Transaction) {
require.Len(t, ch, 1) require.Len(t, ch, 1)
tx := <-ch tx := <-ch
// Response transaction has its hash being precalculated. Check that this hash
// matches the actual one.
cachedHash := tx.Hash()
cp := transaction.Transaction{
Version: tx.Version,
Nonce: tx.Nonce,
SystemFee: tx.SystemFee,
NetworkFee: tx.NetworkFee,
ValidUntilBlock: tx.ValidUntilBlock,
Script: tx.Script,
Attributes: tx.Attributes,
Signers: tx.Signers,
Scripts: tx.Scripts,
Trimmed: tx.Trimmed,
}
actualHash := cp.Hash()
require.Equal(t, actualHash, cachedHash, "transaction hash was changed during ")
require.NoError(t, bc.verifyAndPoolTx(tx, bc.GetMemPool(), bc)) require.NoError(t, bc.verifyAndPoolTx(tx, bc.GetMemPool(), bc))
} }

View file

@ -134,7 +134,11 @@ func (o *Oracle) CreateResponseTx(gasForResponse int64, vub uint32, resp *transa
} }
func (o *Oracle) testVerify(tx *transaction.Transaction) (int64, bool) { func (o *Oracle) testVerify(tx *transaction.Transaction) (int64, bool) {
v, finalize := o.Chain.GetTestVM(trigger.Verification, tx, nil) // (*Blockchain).GetTestVM calls Hash() method of provided transaction; once being called, this
// method caches transaction hash, but tx building is not yet completed and hash will be changed.
// So make a copy of tx to avoid wrong hash caching.
cp := *tx
v, finalize := o.Chain.GetTestVM(trigger.Verification, &cp, 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)