lbcwallet/tx/tx_test.go
Josh Rickmar 413f23ea18 Add support for listtransactions RPC request.
This change adds support for the listtransactions RPC command.  To
properly reply to this command, additonal information about received
transactions was added, and is now saved in an account's tx.bin file.
Additionally, when sending a transaction, a *tx.SendTx is now saved to
the Tx store, and is included in listtransactions replies under the
"send" category.

WARNING: All account's tx.bin and utxo.bin files should be removed
before running with this change, or else the files may not be read
correctly.  Removing tx.bin is not an issue as it was not being used
before, and was being saved with incorrect data.  Removing utxo.bin is
not an issue as it will just trigger a rescan on next start.  File
format versions are now included in both files, so automatic updates
from previous file formats will be possible with future changes.

Fixes #12.
2013-11-26 16:22:15 -05:00

307 lines
7.4 KiB
Go

/*
* Copyright (c) 2013 Conformal Systems LLC <info@conformal.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package tx
import (
"bytes"
"code.google.com/p/go.crypto/ripemd160"
"github.com/conformal/btcwire"
"github.com/davecgh/go-spew/spew"
"io"
"reflect"
"testing"
)
var (
recvtx = &RecvTx{
TxID: [btcwire.HashSize]byte{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31,
},
BlockHash: [btcwire.HashSize]byte{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31,
},
BlockHeight: 69,
Amount: 69,
ReceiverHash: []byte{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19,
},
}
sendtx = &SendTx{
TxID: [btcwire.HashSize]byte{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31,
},
Time: 12345,
BlockHash: [btcwire.HashSize]byte{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31,
},
BlockHeight: 69,
BlockTime: 54321,
BlockIndex: 3,
Receivers: []Pair{
Pair{
PubkeyHash: []byte{
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39,
},
Amount: 69,
},
Pair{
PubkeyHash: []byte{
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
54, 55, 56, 57, 58, 59,
},
Amount: 96,
},
},
}
)
func TestUtxoWriteRead(t *testing.T) {
utxo1 := &Utxo{
AddrHash: [ripemd160.Size]byte{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19,
},
Out: OutPoint{
Hash: [btcwire.HashSize]byte{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31,
},
Index: 1,
},
Subscript: []byte{},
Amt: 69,
Height: 1337,
}
bufWriter := &bytes.Buffer{}
written, err := utxo1.WriteTo(bufWriter)
if err != nil {
t.Error(err)
}
utxoBytes := bufWriter.Bytes()
utxo2 := new(Utxo)
read, err := utxo2.ReadFrom(bytes.NewBuffer(utxoBytes))
if err != nil {
t.Error(err)
}
if written != read {
t.Error("Reading and Writing Utxo: Size Mismatch")
}
if !reflect.DeepEqual(utxo1, utxo2) {
spew.Dump(utxo1, utxo2)
t.Error("Utxos do not match.")
}
truncatedReadBuf := bytes.NewBuffer(utxoBytes)
truncatedReadBuf.Truncate(btcwire.HashSize)
utxo3 := new(Utxo)
n, err := utxo3.ReadFrom(truncatedReadBuf)
if err != io.EOF {
t.Error("Expected err = io.EOF reading from truncated buffer.")
}
if n != btcwire.HashSize {
t.Error("Incorrect number of bytes read from truncated buffer.")
}
}
func TestUtxoStoreWriteRead(t *testing.T) {
store1 := new(UtxoStore)
for i := 0; i < 20; i++ {
utxo := new(Utxo)
for j := range utxo.Out.Hash[:] {
utxo.Out.Hash[j] = byte(i + 1)
}
utxo.Out.Index = uint32(i + 2)
utxo.Subscript = []byte{}
utxo.Amt = uint64(i + 3)
utxo.Height = int32(i + 4)
utxo.BlockHash = [btcwire.HashSize]byte{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31,
}
*store1 = append(*store1, utxo)
}
bufWriter := &bytes.Buffer{}
nWritten, err := store1.WriteTo(bufWriter)
if err != nil {
t.Error(err)
}
if nWritten != int64(bufWriter.Len()) {
t.Errorf("Wrote %v bytes but write buffer has %v bytes.", nWritten, bufWriter.Len())
}
storeBytes := bufWriter.Bytes()
bufReader := bytes.NewBuffer(storeBytes)
if nWritten != int64(bufReader.Len()) {
t.Errorf("Wrote %v bytes but read buffer has %v bytes.", nWritten, bufReader.Len())
}
store2 := new(UtxoStore)
nRead, err := store2.ReadFrom(bufReader)
if err != nil {
t.Error(err)
}
if nWritten != nRead {
t.Errorf("Bytes written (%v) does not match bytes read (%v).", nWritten, nRead)
}
if !reflect.DeepEqual(store1, store2) {
spew.Dump(store1, store2)
t.Error("Stores do not match.")
}
truncatedLen := 101
truncatedReadBuf := bytes.NewBuffer(storeBytes[:truncatedLen])
store3 := new(UtxoStore)
n, err := store3.ReadFrom(truncatedReadBuf)
if err != io.EOF {
t.Errorf("Expected err = io.EOF reading from truncated buffer, got: %v", err)
}
if int(n) != truncatedLen {
t.Errorf("Incorrect number of bytes (%v) read from truncated buffer (len %v).", n, truncatedLen)
}
}
func TestRecvTxWriteRead(t *testing.T) {
bufWriter := &bytes.Buffer{}
n, err := recvtx.WriteTo(bufWriter)
if err != nil {
t.Error(err)
return
}
txBytes := bufWriter.Bytes()
tx := new(RecvTx)
n, err = tx.ReadFrom(bytes.NewBuffer(txBytes))
if err != nil {
t.Error(err)
return
}
if !reflect.DeepEqual(recvtx, tx) {
t.Error("Txs do not match.")
return
}
truncatedReadBuf := bytes.NewBuffer(txBytes)
truncatedReadBuf.Truncate(btcwire.HashSize)
n, err = tx.ReadFrom(truncatedReadBuf)
if err != io.EOF {
t.Error("Expected err = io.EOF reading from truncated buffer.")
return
}
if n != btcwire.HashSize {
t.Error("Incorrect number of bytes read from truncated buffer.")
return
}
}
func TestSendTxWriteRead(t *testing.T) {
bufWriter := &bytes.Buffer{}
n1, err := sendtx.WriteTo(bufWriter)
if err != nil {
t.Error(err)
return
}
txBytes := bufWriter.Bytes()
tx := new(SendTx)
n2, err := tx.ReadFrom(bytes.NewBuffer(txBytes))
if err != nil {
t.Error(err)
return
}
if n1 != n2 {
t.Errorf("Number of bytes written and read mismatch, %d != %d",
n1, n2)
return
}
if !reflect.DeepEqual(sendtx, tx) {
t.Error("Txs do not match.")
return
}
truncatedReadBuf := bytes.NewBuffer(txBytes)
truncatedReadBuf.Truncate(btcwire.HashSize)
n, err := tx.ReadFrom(truncatedReadBuf)
if err != io.EOF {
t.Error("Expected err = io.EOF reading from truncated buffer.")
return
}
if n != btcwire.HashSize {
t.Error("Incorrect number of bytes read from truncated buffer.")
return
}
}
func TestTxStoreWriteRead(t *testing.T) {
s := []interface{}{recvtx, sendtx}
store := TxStore(s)
bufWriter := &bytes.Buffer{}
n1, err := store.WriteTo(bufWriter)
if err != nil {
t.Error(err)
return
}
txsBytes := bufWriter.Bytes()
txs := TxStore{}
n2, err := txs.ReadFrom(bytes.NewBuffer(txsBytes))
if err != nil {
t.Error(err)
return
}
if n1 != n2 {
t.Error("Number of bytes written and read mismatch.")
return
}
if !reflect.DeepEqual(store, txs) {
spew.Dump(store, txs)
t.Error("TxStores do not match.")
return
}
truncatedReadBuf := bytes.NewBuffer(txsBytes)
truncatedReadBuf.Truncate(50)
n, err := txs.ReadFrom(truncatedReadBuf)
if err != io.EOF {
t.Error("Expected err = io.EOF reading from truncated buffer.")
return
}
if n != 50 {
t.Error("Incorrect number of bytes read from truncated buffer.")
return
}
}