From 2b9f288b9c105c34b11a350d9fe20722749b2a74 Mon Sep 17 00:00:00 2001
From: janniks <janniks@users.noreply.github.com>
Date: Tue, 2 Jul 2024 17:58:43 +0200
Subject: [PATCH] fix: update multi-sig signer state

---
 packages/transactions/src/signer.ts         | 24 ++++++++++++---------
 packages/transactions/tests/builder.test.ts |  8 +++++++
 2 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/packages/transactions/src/signer.ts b/packages/transactions/src/signer.ts
index 9724bfb6b..47463af6b 100644
--- a/packages/transactions/src/signer.ts
+++ b/packages/transactions/src/signer.ts
@@ -1,6 +1,7 @@
 import { StacksTransaction } from './transaction';
 import { StacksPrivateKey, StacksPublicKey } from './keys';
 import {
+  isNonSequentialMultiSig,
   isSequentialMultiSig,
   isSingleSig,
   nextVerification,
@@ -38,16 +39,19 @@ export class TransactionSigner {
       }
 
       spendingCondition.fields.forEach(field => {
-        if (field.contents.type === StacksMessageType.MessageSignature) {
-          const signature = field.contents;
-          const nextVerify = nextVerification(
-            this.sigHash,
-            transaction.auth.authType,
-            spendingCondition.fee,
-            spendingCondition.nonce,
-            PubKeyEncoding.Compressed, // always compressed for multisig
-            signature
-          );
+        if (field.contents.type !== StacksMessageType.MessageSignature) return;
+
+        const signature = field.contents;
+        const nextVerify = nextVerification(
+          this.sigHash,
+          transaction.auth.authType,
+          spendingCondition.fee,
+          spendingCondition.nonce,
+          PubKeyEncoding.Compressed, // always compressed for multisig
+          signature
+        );
+
+        if (!isNonSequentialMultiSig(spendingCondition.hashMode)) {
           this.sigHash = nextVerify.nextSigHash;
         }
       });
diff --git a/packages/transactions/tests/builder.test.ts b/packages/transactions/tests/builder.test.ts
index a70a612a2..cbf5cea2a 100644
--- a/packages/transactions/tests/builder.test.ts
+++ b/packages/transactions/tests/builder.test.ts
@@ -412,7 +412,9 @@ test('Make Multi-Sig STX token transfer', async () => {
     anchorMode: AnchorMode.Any,
   });
   const signer = new TransactionSigner(transaction);
+  expect(signer.sigHash).toBe(transaction.signBegin());
   signer.signOrigin(privKeys[0]);
+  expect(signer.sigHash).not.toBe(transaction.signBegin());
   signer.signOrigin(privKeys[1]);
   signer.appendOrigin(pubKeys[2]);
   expect(() => transaction.verifyOrigin()).not.toThrow();
@@ -2629,12 +2631,18 @@ describe('multi-sig', () => {
       const signer = new TransactionSigner(tx);
 
       // sign in reverse order
+      expect(signer.sigHash).toBe(tx.signBegin());
       signer.signOrigin(createStacksPrivateKey(pk3));
+      expect(signer.sigHash).toBe(tx.signBegin());
       signer.signOrigin(createStacksPrivateKey(pk2));
+      expect(signer.sigHash).toBe(tx.signBegin());
       signer.appendOrigin(getPublicKey(createStacksPrivateKey(pk1)));
+      expect(signer.sigHash).toBe(tx.signBegin());
 
       if (isSingleSig(tx.auth.spendingCondition)) throw 'type error';
 
+      expect(signer.sigHash).toBe(tx.signBegin()); // sighash doesn't change for non-sequential multisig
+
       // todo: a `finalize` method would be nice to do this for us
       // we'll manually need to fix the order (for now)
       tx.auth.spendingCondition.fields.reverse();