txsort: Convert tests, optimize, and cleanup code.
- Move hex for test txns into separate files in the testdata directory - Convert tests to table-driven tests - Make comments more consistent with the rest of the codebase - Optimize the input sorting function to perform the hash equivalence check before reversing the bytes so it can be avoided in that case
This commit is contained in:
parent
98fd0a0661
commit
e0e9257790
7 changed files with 129 additions and 203 deletions
1
txsort/testdata/li01-1.hex
vendored
Normal file
1
txsort/testdata/li01-1.hex
vendored
Normal file
File diff suppressed because one or more lines are too long
1
txsort/testdata/li01-2.hex
vendored
Normal file
1
txsort/testdata/li01-2.hex
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
010000000255605dc6f5c3dc148b6da58442b0b2cd422be385eab2ebea4119ee9c268d28350000000049483045022100aa46504baa86df8a33b1192b1b9367b4d729dc41e389f2c04f3e5c7f0559aae702205e82253a54bf5c4f65b7428551554b2045167d6d206dfe6a2e198127d3f7df1501ffffffff55605dc6f5c3dc148b6da58442b0b2cd422be385eab2ebea4119ee9c268d2835010000004847304402202329484c35fa9d6bb32a55a70c0982f606ce0e3634b69006138683bcd12cbb6602200c28feb1e2555c3210f1dddb299738b4ff8bbe9667b68cb8764b5ac17b7adf0001ffffffff0200e1f505000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00180d8f000000004341044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45afac00000000
|
1
txsort/testdata/li01-3.hex
vendored
Normal file
1
txsort/testdata/li01-3.hex
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
0100000001d992e5a888a86d4c7a6a69167a4728ee69497509740fc5f456a24528c340219a000000008b483045022100f0519bdc9282ff476da1323b8ef7ffe33f495c1a8d52cc522b437022d83f6a230220159b61d197fbae01b4a66622a23bc3f1def65d5fa24efd5c26fa872f3a246b8e014104839f9023296a1fabb133140128ca2709f6818c7d099491690bd8ac0fd55279def6a2ceb6ab7b5e4a71889b6e739f09509565eec789e86886f6f936fa42097adeffffffff02000fe208010000001976a914948c765a6914d43f2a7ac177da2c2f6b52de3d7c88ac00e32321000000001976a9140c34f4e29ab5a615d5ea28d4817f12b137d62ed588ac00000000
|
1
txsort/testdata/li01-4.hex
vendored
Normal file
1
txsort/testdata/li01-4.hex
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
01000000059daf0abe7a92618546a9dbcfd65869b6178c66ec21ccfda878c1175979cfd9ef000000004a493046022100c2f7f25be5de6ce88ac3c1a519514379e91f39b31ddff279a3db0b1a229b708b022100b29efbdbd9837cc6a6c7318aa4900ed7e4d65662c34d1622a2035a3a5534a99a01ffffffffd516330ebdf075948da56db13d22632a4fb941122df2884397dda45d451acefb0000000048473044022051243debe6d4f2b433bee0cee78c5c4073ead0e3bde54296dbed6176e128659c022044417bfe16f44eb7b6eb0cdf077b9ce972a332e15395c09ca5e4f602958d266101ffffffffe1f5aa33961227b3c344e57179417ce01b7ccd421117fe2336289b70489883f900000000484730440220593252bb992ce3c85baf28d6e3aa32065816271d2c822398fe7ee28a856bc943022066d429dd5025d3c86fd8fd8a58e183a844bd94aa312cefe00388f57c85b0ca3201ffffffffe207e83718129505e6a7484831442f668164ae659fddb82e9e5421a081fb90d50000000049483045022067cf27eb733e5bcae412a586b25a74417c237161a084167c2a0b439abfebdcb2022100efcc6baa6824b4c5205aa967e0b76d31abf89e738d4b6b014e788c9a8cccaf0c01ffffffffe23b8d9d80a9e9d977fab3c94dbe37befee63822443c3ec5ae5a713ede66c3940000000049483045022020f2eb35036666b1debe0d1d2e77a36d5d9c4e96c1dba23f5100f193dbf524790221008ce79bc1321fb4357c6daee818038d41544749127751726e46b2b320c8b565a201ffffffff0200ba1dd2050000001976a914366a27645806e817a6cd40bc869bdad92fe5509188ac40420f00000000001976a914ee8bd501094a7d5ca318da2506de35e1cb025ddc88ac00000000
|
1
txsort/testdata/li01-5.hex
vendored
Normal file
1
txsort/testdata/li01-5.hex
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
01000000011f636d0003f673b3aeea4971daef16b8eed784cf6e8019a5ae7da4985fbb06e5000000008a47304402205103941e2b11e746dfa817888d422f6e7f4d16dbbfb8ffa61d15ffb924a84b8802202fe861b0f23f17139d15a3374bfc6c7196d371f3d1a324e31cc0aadbba87e53c0141049e7e1b251a7e26cae9ee7553b278ef58ef3c28b4b20134d51b747d9b18b0a19b94b66cef320e2549dec0ea3d725cb4c742f368928b1fb74b4603e24a1e262c80ffffffff0240420f00000000001976a914bcfa0e27218a7c97257b351b03a9eac95c25a23988ac40420f00000000001976a9140c6a68f20bafc678164d171ee4f077adfa9b091688ac00000000
|
|
@ -2,6 +2,9 @@
|
|||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Provides functions for sorting tx inputs and outputs according to BIP LI01
|
||||
// (https://github.com/kristovatlas/rfc/blob/master/bips/bip-li01.mediawiki)
|
||||
|
||||
package txsort
|
||||
|
||||
import (
|
||||
|
@ -11,13 +14,9 @@ import (
|
|||
"github.com/btcsuite/btcd/wire"
|
||||
)
|
||||
|
||||
// TxSort
|
||||
// Provides functions for sorting tx inputs and outputs according to BIP LI01
|
||||
// (https://github.com/kristovatlas/rfc/blob/master/bips/bip-li01.mediawiki)
|
||||
|
||||
// Sort sorts the inputs and outputs of a tx based on BIP LI01
|
||||
// It does not modify the transaction given, but returns a new copy
|
||||
// which has been sorted and may have a different txid.
|
||||
// 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.
|
||||
func Sort(tx *wire.MsgTx) *wire.MsgTx {
|
||||
txCopy := tx.Copy()
|
||||
sort.Sort(sortableInputSlice(txCopy.TxIn))
|
||||
|
@ -25,8 +24,8 @@ func Sort(tx *wire.MsgTx) *wire.MsgTx {
|
|||
return txCopy
|
||||
}
|
||||
|
||||
// IsSorted checks whether tx has inputs and outputs sorted according
|
||||
// to BIP LI01.
|
||||
// IsSorted checks whether tx has inputs and outputs sorted according to BIP
|
||||
// LI01.
|
||||
func IsSorted(tx *wire.MsgTx) bool {
|
||||
if !sort.IsSorted(sortableInputSlice(tx.TxIn)) {
|
||||
return false
|
||||
|
@ -40,45 +39,39 @@ func IsSorted(tx *wire.MsgTx) bool {
|
|||
type sortableInputSlice []*wire.TxIn
|
||||
type sortableOutputSlice []*wire.TxOut
|
||||
|
||||
// for SortableInputSlice and SortableOutputSlice, three functions are needed
|
||||
// For SortableInputSlice and SortableOutputSlice, three functions are needed
|
||||
// to make it sortable with sort.Sort() -- Len, Less, and Swap
|
||||
// Len and Swap are trivial. Less is BIP LI01 specific.
|
||||
func (ins sortableInputSlice) Len() int {
|
||||
return len(ins)
|
||||
}
|
||||
func (outs sortableOutputSlice) Len() int {
|
||||
return len(outs)
|
||||
}
|
||||
|
||||
func (ins sortableInputSlice) Swap(i, j int) {
|
||||
ins[i], ins[j] = ins[j], ins[i]
|
||||
}
|
||||
func (outs sortableOutputSlice) Swap(i, j int) {
|
||||
outs[i], outs[j] = outs[j], outs[i]
|
||||
}
|
||||
func (s sortableInputSlice) Len() int { return len(s) }
|
||||
func (s sortableOutputSlice) Len() int { return len(s) }
|
||||
func (s sortableOutputSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
func (s sortableInputSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
// Input comparison function.
|
||||
// First sort based on input txid (reversed / rpc-style), then index
|
||||
func (ins sortableInputSlice) Less(i, j int) bool {
|
||||
ihash := ins[i].PreviousOutPoint.Hash
|
||||
jhash := ins[j].PreviousOutPoint.Hash
|
||||
for b := 0; b < wire.HashSize/2; b++ {
|
||||
ihash[b], ihash[wire.HashSize-1-b] = ihash[wire.HashSize-1-b], ihash[b]
|
||||
jhash[b], jhash[wire.HashSize-1-b] = jhash[wire.HashSize-1-b], jhash[b]
|
||||
// First sort based on input hash (reversed / rpc-style), then index.
|
||||
func (s sortableInputSlice) Less(i, j int) bool {
|
||||
// Input hashes are the same, so compare the index.
|
||||
ihash := s[i].PreviousOutPoint.Hash
|
||||
jhash := s[j].PreviousOutPoint.Hash
|
||||
if ihash == jhash {
|
||||
return s[i].PreviousOutPoint.Index < s[j].PreviousOutPoint.Index
|
||||
}
|
||||
c := bytes.Compare(ihash[:], jhash[:])
|
||||
if c == 0 {
|
||||
// input txids are the same, compare index
|
||||
return ins[i].PreviousOutPoint.Index < ins[j].PreviousOutPoint.Index
|
||||
|
||||
// At this point, the hashes are not equal, so reverse them to
|
||||
// big-endian and return the result of the comparison.
|
||||
const hashSize = wire.HashSize
|
||||
for b := 0; b < hashSize/2; b++ {
|
||||
ihash[b], ihash[hashSize-1-b] = ihash[hashSize-1-b], ihash[b]
|
||||
jhash[b], jhash[hashSize-1-b] = jhash[hashSize-1-b], jhash[b]
|
||||
}
|
||||
return c == -1.
|
||||
return bytes.Compare(ihash[:], jhash[:]) == -1
|
||||
}
|
||||
|
||||
// Output comparison function.
|
||||
// First sort based on amount (smallest first), then PkScript
|
||||
func (outs sortableOutputSlice) Less(i, j int) bool {
|
||||
if outs[i].Value == outs[j].Value {
|
||||
return bytes.Compare(outs[i].PkScript, outs[j].PkScript) < 0
|
||||
// First sort based on amount (smallest first), then PkScript.
|
||||
func (s sortableOutputSlice) Less(i, j int) bool {
|
||||
if s[i].Value == s[j].Value {
|
||||
return bytes.Compare(s[i].PkScript, s[j].PkScript) < 0
|
||||
}
|
||||
return outs[i].Value < outs[j].Value
|
||||
return s[i].Value < s[j].Value
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue