From 807fa4a720e188ad4fb8fe3026de4edd83a89ee9 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 22 Oct 2021 16:59:16 +0300 Subject: [PATCH] services: allow non-empty inv scripts for contract-based notary witness --- docs/notary.md | 5 +++-- pkg/services/notary/notary.go | 12 +++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/docs/notary.md b/docs/notary.md index 586a63341..ad5f9e14d 100644 --- a/docs/notary.md +++ b/docs/notary.md @@ -376,8 +376,9 @@ the steps to create a signature request: 9. Construct the list of main transactions witnesses (that will be `Scripts` transaction field). Use the following rules: - Contract-based witness should have `Invocation` script that pushes arguments - on stack (it may be empty) and empty `Verification` script. Currently, **only - empty** `Invocation` scripts are supported for contract-based witnesses. + on stack (it may be empty) and empty `Verification` script. If multiple notary + requests provide different `Invocation` scripts then the first one will be used + to construct contract-based witness. - **Notary contract witness** (which is also a contract-based witness) should have empty `Verification` script. `Invocation` script should be of the form [opcode.PUSHDATA1, 64, make([]byte, 64)...], i.e. to be a placeholder for diff --git a/pkg/services/notary/notary.go b/pkg/services/notary/notary.go index 7b4f15fba..af9b77b0a 100644 --- a/pkg/services/notary/notary.go +++ b/pkg/services/notary/notary.go @@ -220,12 +220,18 @@ func (n *Notary) OnNewRequest(payload *payload.P2PNotaryRequest) { } mainHash := hash.NetSha256(uint32(n.Network), r.main).BytesBE() for i, w := range payload.MainTransaction.Scripts { - if r.witnessInfo[i].typ == Contract || // check that we need to fill that witness - len(w.InvocationScript) == 0 || // check that signature for this witness was provided - r.witnessInfo[i].nSigsLeft == 0 { // check that signature wasn't yet added (consider receiving the same payload multiple times) + if len(w.InvocationScript) == 0 || // check that signature for this witness was provided + (r.witnessInfo[i].nSigsLeft == 0 && r.witnessInfo[i].typ != Contract) { // check that signature wasn't yet added (consider receiving the same payload multiple times) continue } switch r.witnessInfo[i].typ { + case Contract: + // Need to check even if r.main.Scripts[i].InvocationScript is already filled in. + err := n.Config.Chain.VerifyWitness(r.main.Signers[i].Account, r.main, &w, n.Config.Chain.GetPolicer().GetMaxVerificationGAS()) + if err != nil { + continue + } + r.main.Scripts[i].InvocationScript = w.InvocationScript case Signature: if r.witnessInfo[i].pubs[0].Verify(w.InvocationScript[2:], mainHash) { r.main.Scripts[i] = w