Merge pull request #1768 from nspcc-dev/notary-tx-fix

services: update Notary transaction size after completion
This commit is contained in:
Roman Khimov 2021-02-24 12:53:28 +03:00 committed by GitHub
commit fdcd8c2209
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 1 deletions

View file

@ -20,6 +20,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/network/payload"
"github.com/nspcc-dev/neo-go/pkg/services/notary"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
@ -184,12 +185,18 @@ func TestNotary(t *testing.T) {
}
scripts[i].InvocationScript = append([]byte{byte(opcode.PUSHDATA1), 64}, requesters[i].PrivateKey().Sign(main.GetSignedPart())...)
main.Scripts = scripts
_ = main.Size() // for size update test
var fallback *transaction.Transaction
if len(NVBincrements) == len(requesters) {
fallback = createFallbackTx(requesters[i], main, NVBincrements[i])
} else {
fallback = createFallbackTx(requesters[i], main)
}
_ = fallback.Size() // for size update test
payloads[i] = &payload.P2PNotaryRequest{
MainTransaction: main,
FallbackTransaction: fallback,
@ -255,6 +262,10 @@ func TestNotary(t *testing.T) {
require.NotNil(t, completedTx, errors.New("main transaction expected to be completed"))
require.Equal(t, nKeys+1, len(completedTx.Signers))
require.Equal(t, nKeys+1, len(completedTx.Scripts))
// check that tx size was updated
require.Equal(t, io.GetVarSize(completedTx), completedTx.Size())
interopCtx := bc.newInteropContext(trigger.Verification, bc.dao, nil, completedTx)
for i, req := range requests {
require.Equal(t, req.MainTransaction.Scripts[i], completedTx.Scripts[i])
@ -305,6 +316,10 @@ func TestNotary(t *testing.T) {
InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, acc1.PrivateKey().Sign(req.FallbackTransaction.GetSignedPart())...),
VerificationScript: []byte{},
}, completedTx.Scripts[0])
// check that tx size was updated
require.Equal(t, io.GetVarSize(completedTx), completedTx.Size())
interopCtx := bc.newInteropContext(trigger.Verification, bc.dao, nil, completedTx)
_, err := bc.verifyHashAgainstScript(completedTx.Signers[1].Account, &completedTx.Scripts[1], interopCtx, -1)
require.NoError(t, err)

View file

@ -15,6 +15,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/network/payload"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm"
@ -316,7 +317,22 @@ func (n *Notary) finalize(tx *transaction.Transaction) error {
break
}
}
return n.onTransaction(tx)
newTx, err := updateTxSize(tx)
if err != nil {
return fmt.Errorf("failed to update completed transaction's size: %w", err)
}
return n.onTransaction(newTx)
}
// updateTxSize returns transaction with re-calculated size and an error.
func updateTxSize(tx *transaction.Transaction) (*transaction.Transaction, error) {
bw := io.NewBufBinWriter()
tx.EncodeBinary(bw.BinWriter)
if bw.Err != nil {
return nil, fmt.Errorf("encode binary: %w", bw.Err)
}
return transaction.NewTransactionFromBytes(tx.Network, tx.Bytes())
}
// verifyIncompleteWitnesses checks that tx either doesn't have all witnesses attached (in this case none of them