From 0df67ee0646e5fb24d4d25cb0b58abc642cd80a9 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 23 Oct 2015 04:42:59 -0500 Subject: [PATCH] txsort: Add InPlaceSort function. This adds a new function with loud warnings which allows sorting a transaction in place by mutating it. This is more efficient for the caller if they are the ones creating the transaction and are sure it will not invalid any cache or containing structures. The Sort function which makes a copy and is therefore does not mutate the passed transaction is still available and the default method. --- txsort/txsort.go | 17 +++++++++++++++++ txsort/txsort_test.go | 10 ++++++++++ 2 files changed, 27 insertions(+) diff --git a/txsort/txsort.go b/txsort/txsort.go index b915cb5..9a32036 100644 --- a/txsort/txsort.go +++ b/txsort/txsort.go @@ -14,6 +14,23 @@ import ( "github.com/btcsuite/btcd/wire" ) +// InPlaceSort modifies the passed transaction inputs and outputs to be sorted +// based on BIP LI01. +// +// WARNING: This function must NOT be called with published transactions since +// it will mutate the transaction if it's not already sorted. This can cause +// issues if you mutate a tx in a block, for example, which would invalidate the +// block. It could also cause cached hashes, such as in a btcutil.Tx to become +// invalidated. +// +// The function should only be used if the caller is creating the transaction or +// is otherwise 100% positive mutating will not cause adverse affects due to +// other dependencies. +func InPlaceSort(tx *wire.MsgTx) { + sort.Sort(sortableInputSlice(tx.TxIn)) + sort.Sort(sortableOutputSlice(tx.TxOut)) +} + // Sort returns a new transaction with the inputs and outputs sorted based on // BIP LI01. The passed transaction is not modified and the new transaction // might have a different hash if any sorting was done. diff --git a/txsort/txsort_test.go b/txsort/txsort_test.go index ef5db18..bcf6d2b 100644 --- a/txsort/txsort_test.go +++ b/txsort/txsort_test.go @@ -110,5 +110,15 @@ func TestSort(t *testing.T) { test.unsortedHash) continue } + + // Now sort the transaction using the mutable version and ensure + // the resulting hash is the expected value. + txsort.InPlaceSort(&tx) + if got := tx.TxSha().String(); got != test.sortedHash { + t.Errorf("SortMutate (%s): sorted hash does not match "+ + "expected - got %v, want %v", test.name, got, + test.sortedHash) + continue + } } }