@@ -480,6 +480,56 @@ func TestIntegrationTransactionRemoveSignature(t *testing.T) {
480480 require .NoError (t , err )
481481}
482482
483+ // TestIntegrationTransactionRemoveSignatureIsAppliedOnExecute proves the removal actually reaches
484+ // the wire: after removing the account key we execute WITHOUT re-signing, and the network rejects
485+ // the delete with INVALID_SIGNATURE. This is stronger than the GetSignatures check (which only
486+ // reads the in-memory sig map) because it confirms the removed signature is genuinely absent from
487+ // the bytes transmitted at build/execute time and is not resurrected.
488+ func TestIntegrationTransactionRemoveSignatureIsAppliedOnExecute (t * testing.T ) {
489+ t .Parallel ()
490+ env := NewIntegrationTestEnv (t )
491+ defer CloseIntegrationTestEnv (env , nil )
492+
493+ newKey , err := PrivateKeyGenerateEd25519 ()
494+ require .NoError (t , err )
495+
496+ resp , err := NewAccountCreateTransaction ().
497+ SetKeyWithoutAlias (newKey .PublicKey ()).
498+ SetNodeAccountIDs (env .NodeAccountIDs ).
499+ Execute (env .Client )
500+ require .NoError (t , err )
501+
502+ receipt , err := resp .SetValidateStatus (true ).GetReceipt (env .Client )
503+ require .NoError (t , err )
504+
505+ tx , err := NewAccountDeleteTransaction ().
506+ SetNodeAccountIDs ([]AccountID {resp .NodeID }).
507+ SetAccountID (* receipt .AccountID ).
508+ SetTransferAccountID (env .Client .GetOperatorAccountID ()).
509+ FreezeWith (env .Client )
510+ require .NoError (t , err )
511+
512+ // Sign with the account key, confirm it is present, then remove it.
513+ _ , err = newKey .SignTransaction (tx )
514+ require .NoError (t , err )
515+
516+ signatures , err := tx .GetSignatures ()
517+ require .NoError (t , err )
518+ require .True (t , _SignaturesContainKey (signatures , newKey .PublicKey ()))
519+
520+ removed , err := tx .RemoveSignature (newKey .PublicKey ())
521+ require .NoError (t , err )
522+ require .NotEmpty (t , removed )
523+
524+ // Execute WITHOUT re-signing. The operator (payer) signature is re-applied automatically, but the
525+ // account's required signature was removed, so the delete must be rejected with INVALID_SIGNATURE.
526+ resp , err = tx .Execute (env .Client )
527+ require .NoError (t , err )
528+
529+ _ , err = resp .SetValidateStatus (true ).GetReceipt (env .Client )
530+ require .ErrorContains (t , err , "INVALID_SIGNATURE" )
531+ }
532+
483533func TestIntegrationTransactionRemoveAllSignatures (t * testing.T ) {
484534 t .Parallel ()
485535 env := NewIntegrationTestEnv (t )
@@ -504,28 +554,40 @@ func TestIntegrationTransactionRemoveAllSignatures(t *testing.T) {
504554 FreezeWith (env .Client )
505555 require .NoError (t , err )
506556
507- // Sign with both the operator and the account key so more than one signature is present.
508- _ , err = tx .SignWithOperator (env .Client )
557+ // Sign with the account key plus a second, unrelated key so more than one signature is present on
558+ // the wire. Both are applied via SignTransaction, which materializes the signature into the sig
559+ // map immediately (unlike the operator signer, which is deferred until build/execute time and so
560+ // would not yet appear in GetSignatures/RemoveAllSignatures).
561+ secondKey , err := PrivateKeyGenerateEd25519 ()
509562 require .NoError (t , err )
510563 _ , err = newKey .SignTransaction (tx )
511564 require .NoError (t , err )
565+ _ , err = secondKey .SignTransaction (tx )
566+ require .NoError (t , err )
512567
568+ // Both keys must be present before removal.
513569 signatures , err := tx .GetSignatures ()
514570 require .NoError (t , err )
515571 require .True (t , _SignaturesContainKey (signatures , newKey .PublicKey ()))
572+ require .True (t , _SignaturesContainKey (signatures , secondKey .PublicKey ()))
516573
517- // Strip everything: the returned map is keyed by every public key that had signed.
574+ // Strip everything: the returned map is keyed by every public key that had signed, so both keys
575+ // must appear in it.
518576 removed , err := tx .RemoveAllSignatures ()
519577 require .NoError (t , err )
520- require .NotEmpty (t , removed )
578+ require .Len (t , removed , 2 )
521579
522- var newKeyFound bool
580+ var newKeyFound , secondKeyFound bool
523581 for key := range removed {
524- if key .String () == newKey .PublicKey ().String () {
582+ switch key .String () {
583+ case newKey .PublicKey ().String ():
525584 newKeyFound = true
585+ case secondKey .PublicKey ().String ():
586+ secondKeyFound = true
526587 }
527588 }
528589 require .True (t , newKeyFound )
590+ require .True (t , secondKeyFound )
529591
530592 // Every node's signature set is now empty.
531593 signatures , err = tx .GetSignatures ()
0 commit comments