diff --git a/txnbuild/transaction.go b/txnbuild/transaction.go index e00bdafb77..c02d349b1f 100644 --- a/txnbuild/transaction.go +++ b/txnbuild/transaction.go @@ -323,6 +323,12 @@ func (t *Transaction) SignHashX(preimage []byte) (*Transaction, error) { return t.clone(extendedSignatures), nil } +// ClearSignatures returns a new Transaction instance which extends the current instance +// with signatures removed. +func (t *Transaction) ClearSignatures() (*Transaction, error) { + return t.clone(nil), nil +} + // AddSignatureDecorated returns a new Transaction instance which extends the current instance // with an additional decorated signature(s). func (t *Transaction) AddSignatureDecorated(signature ...xdr.DecoratedSignature) (*Transaction, error) { @@ -519,6 +525,12 @@ func (t *FeeBumpTransaction) SignHashX(preimage []byte) (*FeeBumpTransaction, er return t.clone(extendedSignatures), nil } +// ClearSignatures returns a new Transaction instance which extends the current instance +// with signatures removed. +func (t *FeeBumpTransaction) ClearSignatures() (*FeeBumpTransaction, error) { + return t.clone(nil), nil +} + // AddSignatureBase64 returns a new FeeBumpTransaction instance which extends the current instance // with an additional signature derived from the given base64-encoded signature. func (t *FeeBumpTransaction) AddSignatureBase64(network, publicKey, signature string) (*FeeBumpTransaction, error) { diff --git a/txnbuild/transaction_test.go b/txnbuild/transaction_test.go index 7269d696e9..5b0fe18d98 100644 --- a/txnbuild/transaction_test.go +++ b/txnbuild/transaction_test.go @@ -3,13 +3,13 @@ package txnbuild import ( "crypto/sha256" "encoding/base64" - "github.com/stellar/go/price" "strings" "testing" "time" "github.com/stellar/go/keypair" "github.com/stellar/go/network" + "github.com/stellar/go/price" "github.com/stellar/go/strkey" "github.com/stellar/go/xdr" "github.com/stretchr/testify/assert" @@ -1692,6 +1692,83 @@ func TestAddSignatureBase64(t *testing.T) { assert.Equal(t, expected, actual, "base64 xdr should match") } +func TestTransaction_ClearSignatures(t *testing.T) { + kp0 := newKeypair0() + kp1 := newKeypair1() + + tx, err := NewTransaction( + TransactionParams{ + SourceAccount: &SimpleAccount{AccountID: kp0.Address(), Sequence: int64(9605939170639898)}, + Operations: []Operation{&CreateAccount{ + Destination: "GCCOBXW2XQNUSL467IEILE6MMCNRR66SSVL4YQADUNYYNUVREF3FIV2Z", + Amount: "10", + SourceAccount: kp1.Address(), + }}, + BaseFee: MinBaseFee, + Timebounds: NewInfiniteTimeout(), + }, + ) + require.NoError(t, err) + require.Len(t, tx.Signatures(), 0) + + txWithSig, err := tx.Sign(network.TestNetworkPassphrase, kp0) + require.NoError(t, err) + require.Len(t, txWithSig.Signatures(), 1) + + txSigCleared, err := txWithSig.ClearSignatures() + require.NoError(t, err) + require.Len(t, txSigCleared.Signatures(), 0) + + expected, err := tx.Base64() + assert.NoError(t, err) + actual, err := txSigCleared.Base64() + assert.NoError(t, err) + assert.Equal(t, expected, actual) +} + +func TestFeeBumpTransaction_ClearSignatures(t *testing.T) { + kp0 := newKeypair0() + kp1 := newKeypair1() + + tx, err := NewTransaction(TransactionParams{ + SourceAccount: &SimpleAccount{AccountID: kp0.Address(), Sequence: int64(9605939170639898)}, + Operations: []Operation{&CreateAccount{ + Destination: "GCCOBXW2XQNUSL467IEILE6MMCNRR66SSVL4YQADUNYYNUVREF3FIV2Z", + Amount: "10", + SourceAccount: kp1.Address(), + }}, + BaseFee: MinBaseFee, + Timebounds: NewInfiniteTimeout(), + }) + require.NoError(t, err) + require.Len(t, tx.Signatures(), 0) + txWithSig, err := tx.Sign(network.TestNetworkPassphrase, kp0) + require.NoError(t, err) + require.Len(t, txWithSig.Signatures(), 1) + + fbtx, err := NewFeeBumpTransaction(FeeBumpTransactionParams{ + Inner: txWithSig, + FeeAccount: kp0.Address(), + BaseFee: MinBaseFee, + }) + require.NoError(t, err) + require.Len(t, fbtx.Signatures(), 0) + + fbtxWithSig, err := fbtx.Sign(network.TestNetworkPassphrase, kp0) + require.NoError(t, err) + require.Len(t, fbtxWithSig.Signatures(), 1) + + fbtxSigCleared, err := fbtxWithSig.ClearSignatures() + require.NoError(t, err) + require.Len(t, fbtxSigCleared.Signatures(), 0) + + expected, err := fbtx.Base64() + assert.NoError(t, err) + actual, err := fbtxSigCleared.Base64() + assert.NoError(t, err) + assert.Equal(t, expected, actual) +} + func TestReadChallengeTx_validSignedByServerAndClient(t *testing.T) { serverKP := newKeypair0() clientKP := newKeypair1()