From caa14e930b71210463e373ad22bf2d037f5fbfb6 Mon Sep 17 00:00:00 2001 From: Tamir Sen Date: Tue, 2 Jun 2020 11:49:02 +0200 Subject: [PATCH] Add ToXDR functions which do not return errors --- txnbuild/CHANGELOG.md | 1 + txnbuild/signers_test.go | 43 ++++++++++++++++++++++++++++------------ txnbuild/transaction.go | 32 ++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 13 deletions(-) diff --git a/txnbuild/CHANGELOG.md b/txnbuild/CHANGELOG.md index 2327b35e77..2c2ff1fbda 100644 --- a/txnbuild/CHANGELOG.md +++ b/txnbuild/CHANGELOG.md @@ -6,6 +6,7 @@ file. This project adheres to [Semantic Versioning](http://semver.org/). ## Unreleased * `txnbuild` now generates V1 transaction envelopes which are only supported by Protocol 13 ([#2640](https://github.com/stellar/go/pull/2640)) +* Add `ToXDR()` functions for `Transaction` and `FeeBumpTransaction` instances which return xdr transaction envelopes without errors ([#2651](https://github.com/stellar/go/pull/2651)) ## [v3.1.0](https://github.com/stellar/go/releases/tag/horizonclient-v3.1.0) - 2020-05-14 diff --git a/txnbuild/signers_test.go b/txnbuild/signers_test.go index ed5a68adb4..f9d158ea66 100644 --- a/txnbuild/signers_test.go +++ b/txnbuild/signers_test.go @@ -436,12 +436,15 @@ func TestSetOptionsMultSigners(t *testing.T) { assert.Equal(t, expected, received, "Base 64 XDR should match") } -type SignatureList interface { +type transactionCommon interface { Signatures() []xdr.DecoratedSignature Hash(networkStr string) ([32]byte, error) + Base64() (string, error) + TxEnvelope() (xdr.TransactionEnvelope, error) + ToXDR() xdr.TransactionEnvelope } -func verifySignatures(t *testing.T, tx SignatureList, signers ...*keypair.Full) { +func verifySignatures(t *testing.T, tx transactionCommon, signers ...*keypair.Full) { assert.Len(t, tx.Signatures(), len(signers)) hash, err := tx.Hash(network.TestNetworkPassphrase) @@ -452,6 +455,25 @@ func verifySignatures(t *testing.T, tx SignatureList, signers ...*keypair.Full) } } +func assertBase64(t *testing.T, tx transactionCommon) string { + base64, err := tx.Base64() + assert.NoError(t, err) + + envCopy, err := tx.TxEnvelope() + assert.NoError(t, err) + envCopyBase64, err := xdr.MarshalBase64(envCopy) + assert.NoError(t, err) + + envRef := tx.ToXDR() + envRefBase64, err := xdr.MarshalBase64(envRef) + assert.NoError(t, err) + + assert.Equal(t, base64, envCopyBase64) + assert.Equal(t, base64, envRefBase64) + + return base64 +} + func TestSigningImmutability(t *testing.T) { kp0, kp1, kp2 := newKeypair0(), newKeypair1(), newKeypair2() @@ -466,18 +488,15 @@ func TestSigningImmutability(t *testing.T) { assert.NoError(t, err) root, err = root.Sign(network.TestNetworkPassphrase, kp0) assert.NoError(t, err) - rootB64, err := root.Base64() - assert.NoError(t, err) + rootB64 := assertBase64(t, root) left, err := root.Sign(network.TestNetworkPassphrase, kp1) assert.NoError(t, err) - leftB64, err := left.Base64() - assert.NoError(t, err) + leftB64 := assertBase64(t, left) right, err := root.Sign(network.TestNetworkPassphrase, kp2) assert.NoError(t, err) - rightB64, err := right.Base64() - assert.NoError(t, err) + rightB64 := assertBase64(t, right) expectedRootB64, err := newSignedTransaction( params, network.TestNetworkPassphrase, kp0, @@ -521,18 +540,16 @@ func TestFeeBumpSigningImmutability(t *testing.T) { root, err := NewFeeBumpTransaction(params) assert.NoError(t, err) root, err = root.Sign(network.TestNetworkPassphrase, kp1) - rootB64, err := root.Base64() assert.NoError(t, err) + rootB64 := assertBase64(t, root) left, err := root.Sign(network.TestNetworkPassphrase, kp0) assert.NoError(t, err) - leftB64, err := left.Base64() - assert.NoError(t, err) + leftB64 := assertBase64(t, left) right, err := root.Sign(network.TestNetworkPassphrase, kp2) assert.NoError(t, err) - rightB64, err := right.Base64() - assert.NoError(t, err) + rightB64 := assertBase64(t, right) expectedRootB64, err := newSignedFeeBumpTransaction( params, network.TestNetworkPassphrase, kp1, diff --git a/txnbuild/transaction.go b/txnbuild/transaction.go index 8a6185b551..e5abb03feb 100644 --- a/txnbuild/transaction.go +++ b/txnbuild/transaction.go @@ -319,6 +319,23 @@ func (t *Transaction) TxEnvelope() (xdr.TransactionEnvelope, error) { return cloneEnvelope(t.envelope, t.signatures) } +// ToXDR is like TxEnvelope except that the transaction envelope returned by ToXDR +// should not be modified because any changes applied to the transaction envelope may +// affect the internals of the Transaction instance. +func (t *Transaction) ToXDR() xdr.TransactionEnvelope { + env := t.envelope + switch env.Type { + case xdr.EnvelopeTypeEnvelopeTypeTx: + env.V1.Signatures = t.signatures + case xdr.EnvelopeTypeEnvelopeTypeTxV0: + env.V0.Signatures = t.signatures + default: + panic("invalid transaction type: " + env.Type.String()) + } + + return env +} + // MarshalBinary returns the binary XDR representation of the transaction envelope. func (t *Transaction) MarshalBinary() ([]byte, error) { return marshallBinary(t.envelope, t.signatures) @@ -432,6 +449,21 @@ func (t *FeeBumpTransaction) TxEnvelope() (xdr.TransactionEnvelope, error) { return cloneEnvelope(t.envelope, t.signatures) } +// ToXDR is like TxEnvelope except that the transaction envelope returned by ToXDR +// should not be modified because any changes applied to the transaction envelope may +// affect the internals of the FeeBumpTransaction instance. +func (t *FeeBumpTransaction) ToXDR() xdr.TransactionEnvelope { + env := t.envelope + switch env.Type { + case xdr.EnvelopeTypeEnvelopeTypeTxFeeBump: + env.FeeBump.Signatures = t.signatures + default: + panic("invalid transaction type: " + env.Type.String()) + } + + return env +} + // MarshalBinary returns the binary XDR representation of the transaction envelope. func (t *FeeBumpTransaction) MarshalBinary() ([]byte, error) { return marshallBinary(t.envelope, t.signatures)