txsort: Convert to package
This converts the txsort code into a separate package and renames 'TxSort' and 'IsTxSorted' to 'Sort' an `IsSorted`, respectively. It also adds a 'doc.go' and 'README.md' so it is consistent with the other packages.
This commit is contained in:
parent
5fd45e8085
commit
98fd0a0661
4 changed files with 83 additions and 34 deletions
44
txsort/README.md
Normal file
44
txsort/README.md
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
txsort
|
||||||
|
======
|
||||||
|
|
||||||
|
[![Build Status](http://img.shields.io/travis/btcsuite/btcutil.svg)]
|
||||||
|
(https://travis-ci.org/btcsuite/btcutil) [![ISC License]
|
||||||
|
(http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org)
|
||||||
|
|
||||||
|
Package txsort provides the transaction sorting according to BIPLI01.
|
||||||
|
|
||||||
|
BIPLI01 defines a standard lexicographical sort order of transaction inputs and
|
||||||
|
outputs. This is useful to standardize transactions for faster multi-party
|
||||||
|
agreement as well as preventing information leaks in a single-party use case.
|
||||||
|
|
||||||
|
The BIP goes into more detail, but for a quick and simplistic overview, the
|
||||||
|
order for inputs is defined as first sorting on the previous output hash and
|
||||||
|
then on the index as a tie breaker. The order for outputs is defined as first
|
||||||
|
sorting on the amount and then on the raw public key script bytes as a tie
|
||||||
|
breaker.
|
||||||
|
|
||||||
|
A comprehensive suite of tests is provided to ensure proper functionality.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)]
|
||||||
|
(http://godoc.org/github.com/btcsuite/btcutil/txsort)
|
||||||
|
|
||||||
|
Full `go doc` style documentation for the project can be viewed online without
|
||||||
|
installing this package by using the GoDoc site here:
|
||||||
|
http://godoc.org/github.com/btcsuite/btcutil/txsort
|
||||||
|
|
||||||
|
You can also view the documentation locally once the package is installed with
|
||||||
|
the `godoc` tool by running `godoc -http=":6060"` and pointing your browser to
|
||||||
|
http://localhost:6060/pkg/github.com/btcsuite/btcutil/txsort
|
||||||
|
|
||||||
|
## Installation and Updating
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ go get -u github.com/btcsuite/btcutil/txsort
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Package txsort is licensed under the [copyfree](http://copyfree.org) ISC
|
||||||
|
License.
|
20
txsort/doc.go
Normal file
20
txsort/doc.go
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright (c) 2015 The btcsuite developers
|
||||||
|
// Use of this source code is governed by an ISC
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package txsort provides the transaction sorting according to BIPLI01.
|
||||||
|
|
||||||
|
Overview
|
||||||
|
|
||||||
|
BIPLI01 defines a standard lexicographical sort order of transaction inputs and
|
||||||
|
outputs. This is useful to standardize transactions for faster multi-party
|
||||||
|
agreement as well as preventing information leaks in a single-party use case.
|
||||||
|
|
||||||
|
The BIP goes into more detail, but for a quick and simplistic overview, the
|
||||||
|
order for inputs is defined as first sorting on the previous output hash and
|
||||||
|
then on the index as a tie breaker. The order for outputs is defined as first
|
||||||
|
sorting on the amount and then on the raw public key script bytes as a tie
|
||||||
|
breaker.
|
||||||
|
*/
|
||||||
|
package txsort
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package btcutil
|
package txsort
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
@ -15,19 +15,19 @@ import (
|
||||||
// Provides functions for sorting tx inputs and outputs according to BIP LI01
|
// Provides functions for sorting tx inputs and outputs according to BIP LI01
|
||||||
// (https://github.com/kristovatlas/rfc/blob/master/bips/bip-li01.mediawiki)
|
// (https://github.com/kristovatlas/rfc/blob/master/bips/bip-li01.mediawiki)
|
||||||
|
|
||||||
// TxSort sorts the inputs and outputs of a tx based on BIP LI01
|
// 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
|
// It does not modify the transaction given, but returns a new copy
|
||||||
// which has been sorted and may have a different txid.
|
// which has been sorted and may have a different txid.
|
||||||
func TxSort(tx *wire.MsgTx) *wire.MsgTx {
|
func Sort(tx *wire.MsgTx) *wire.MsgTx {
|
||||||
txCopy := tx.Copy()
|
txCopy := tx.Copy()
|
||||||
sort.Sort(sortableInputSlice(txCopy.TxIn))
|
sort.Sort(sortableInputSlice(txCopy.TxIn))
|
||||||
sort.Sort(sortableOutputSlice(txCopy.TxOut))
|
sort.Sort(sortableOutputSlice(txCopy.TxOut))
|
||||||
return txCopy
|
return txCopy
|
||||||
}
|
}
|
||||||
|
|
||||||
// TxIsSorted checks whether tx has inputs and outputs sorted according
|
// IsSorted checks whether tx has inputs and outputs sorted according
|
||||||
// to BIP LI01.
|
// to BIP LI01.
|
||||||
func TxIsSorted(tx *wire.MsgTx) bool {
|
func IsSorted(tx *wire.MsgTx) bool {
|
||||||
if !sort.IsSorted(sortableInputSlice(tx.TxIn)) {
|
if !sort.IsSorted(sortableInputSlice(tx.TxIn)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package btcutil_test
|
package txsort_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
@ -10,26 +10,11 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil/txsort"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestSortTx tests SortTx function
|
// TestSort tests Sort function
|
||||||
func TestSortTx(t *testing.T) {
|
func TestSort(t *testing.T) {
|
||||||
// Use block 100,000 transaction 1. Already sorted.
|
|
||||||
testTx := Block100000.Transactions[1]
|
|
||||||
sortedTx := btcutil.TxSort(testTx)
|
|
||||||
|
|
||||||
testTxid := testTx.TxSha()
|
|
||||||
sortedTxid := sortedTx.TxSha()
|
|
||||||
if !testTxid.IsEqual(&sortedTxid) {
|
|
||||||
t.Errorf("Sorted TxSha mismatch - got %v, want %v",
|
|
||||||
testTxid.String(), sortedTxid.String())
|
|
||||||
}
|
|
||||||
if !btcutil.TxIsSorted(testTx) {
|
|
||||||
t.Errorf("testTx %v is sorted but reported as unsorted",
|
|
||||||
testTxid.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Example 1 0a6a357e2f7796444e02638749d9611c008b253fb55f5dc88b739b230ed0c4c3
|
// Example 1 0a6a357e2f7796444e02638749d9611c008b253fb55f5dc88b739b230ed0c4c3
|
||||||
// test transaction 0a6a357e... which is the first test case of BIPLI01
|
// test transaction 0a6a357e... which is the first test case of BIPLI01
|
||||||
li01Tx1bytes, err := hex.DecodeString(LI01Hex1)
|
li01Tx1bytes, err := hex.DecodeString(LI01Hex1)
|
||||||
|
@ -43,11 +28,11 @@ func TestSortTx(t *testing.T) {
|
||||||
t.Errorf("Failed to Deserialize li01Tx from byte slice")
|
t.Errorf("Failed to Deserialize li01Tx from byte slice")
|
||||||
}
|
}
|
||||||
|
|
||||||
if btcutil.TxIsSorted(&li01Tx1) {
|
if txsort.IsSorted(&li01Tx1) {
|
||||||
t.Errorf("LI01 Test Transaction 1 seen as sorted, but isn't")
|
t.Errorf("LI01 Test Transaction 1 seen as sorted, but isn't")
|
||||||
}
|
}
|
||||||
|
|
||||||
li01Tx1Sorted := btcutil.TxSort(&li01Tx1)
|
li01Tx1Sorted := txsort.Sort(&li01Tx1)
|
||||||
// txid of 0a6a357e... becomes 839503c... when sorted
|
// txid of 0a6a357e... becomes 839503c... when sorted
|
||||||
wantSha := newShaHashFromStr("839503cb611a3e3734bd521c608f881be2293ff77b7384057ab994c794fce623")
|
wantSha := newShaHashFromStr("839503cb611a3e3734bd521c608f881be2293ff77b7384057ab994c794fce623")
|
||||||
|
|
||||||
|
@ -78,11 +63,11 @@ func TestSortTx(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to Deserialize li01Tx from byte slice")
|
t.Errorf("Failed to Deserialize li01Tx from byte slice")
|
||||||
}
|
}
|
||||||
if !btcutil.TxIsSorted(&li01Tx2) {
|
if !txsort.IsSorted(&li01Tx2) {
|
||||||
t.Errorf("LI01 Test Transaction 2 seen as unsorted, but it is sorted")
|
t.Errorf("LI01 Test Transaction 2 seen as unsorted, but it is sorted")
|
||||||
}
|
}
|
||||||
|
|
||||||
li01Tx2Sorted := btcutil.TxSort(&li01Tx2)
|
li01Tx2Sorted := txsort.Sort(&li01Tx2)
|
||||||
|
|
||||||
// txid of 28204cad... stays the same when sorted
|
// txid of 28204cad... stays the same when sorted
|
||||||
wantSha = newShaHashFromStr("28204cad1d7fc1d199e8ef4fa22f182de6258a3eaafe1bbe56ebdcacd3069a5f")
|
wantSha = newShaHashFromStr("28204cad1d7fc1d199e8ef4fa22f182de6258a3eaafe1bbe56ebdcacd3069a5f")
|
||||||
|
@ -104,11 +89,11 @@ func TestSortTx(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to Deserialize li01Tx3 from byte slice")
|
t.Errorf("Failed to Deserialize li01Tx3 from byte slice")
|
||||||
}
|
}
|
||||||
if btcutil.TxIsSorted(&li01Tx3) {
|
if txsort.IsSorted(&li01Tx3) {
|
||||||
t.Errorf("LI01 Test Transaction 3 seen as sorted, but isn't")
|
t.Errorf("LI01 Test Transaction 3 seen as sorted, but isn't")
|
||||||
}
|
}
|
||||||
|
|
||||||
li01Tx3Sorted := btcutil.TxSort(&li01Tx3)
|
li01Tx3Sorted := txsort.Sort(&li01Tx3)
|
||||||
|
|
||||||
// txid of 8131ffb0... changes to 0a8c246... when sorted
|
// txid of 8131ffb0... changes to 0a8c246... when sorted
|
||||||
wantSha = newShaHashFromStr("0a8c246c55f6b82f094d211f4f57167bf2ea4898741d218b09bdb2536fd8d13f")
|
wantSha = newShaHashFromStr("0a8c246c55f6b82f094d211f4f57167bf2ea4898741d218b09bdb2536fd8d13f")
|
||||||
|
@ -130,11 +115,11 @@ func TestSortTx(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to Deserialize li01Tx4 from byte slice")
|
t.Errorf("Failed to Deserialize li01Tx4 from byte slice")
|
||||||
}
|
}
|
||||||
if btcutil.TxIsSorted(&li01Tx4) {
|
if txsort.IsSorted(&li01Tx4) {
|
||||||
t.Errorf("LI01 Test Transaction 4 seen as sorted, but isn't")
|
t.Errorf("LI01 Test Transaction 4 seen as sorted, but isn't")
|
||||||
}
|
}
|
||||||
|
|
||||||
li01Tx4Sorted := btcutil.TxSort(&li01Tx4)
|
li01Tx4Sorted := txsort.Sort(&li01Tx4)
|
||||||
|
|
||||||
// txid of 8131ffb0... changes to 0a8c246... when sorted
|
// txid of 8131ffb0... changes to 0a8c246... when sorted
|
||||||
wantSha = newShaHashFromStr("a3196553b928b0b6154b002fa9a1ce875adabc486fedaaaf4c17430fd4486329")
|
wantSha = newShaHashFromStr("a3196553b928b0b6154b002fa9a1ce875adabc486fedaaaf4c17430fd4486329")
|
||||||
|
@ -156,11 +141,11 @@ func TestSortTx(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to Deserialize li01Tx5 from byte slice")
|
t.Errorf("Failed to Deserialize li01Tx5 from byte slice")
|
||||||
}
|
}
|
||||||
if btcutil.TxIsSorted(&li01Tx5) {
|
if txsort.IsSorted(&li01Tx5) {
|
||||||
t.Errorf("LI01 Test Transaction 5 seen as sorted, but isn't")
|
t.Errorf("LI01 Test Transaction 5 seen as sorted, but isn't")
|
||||||
}
|
}
|
||||||
|
|
||||||
li01Tx5Sorted := btcutil.TxSort(&li01Tx5)
|
li01Tx5Sorted := txsort.Sort(&li01Tx5)
|
||||||
|
|
||||||
// txid of ff85e8f... changes to 9a6c247... when sorted
|
// txid of ff85e8f... changes to 9a6c247... when sorted
|
||||||
wantSha = newShaHashFromStr("9a6c24746de024f77cac9b2138694f11101d1c66289261224ca52a25155a7c94")
|
wantSha = newShaHashFromStr("9a6c24746de024f77cac9b2138694f11101d1c66289261224ca52a25155a7c94")
|
Loading…
Reference in a new issue