Save index as well as tx hash for outputs.
This commit is contained in:
parent
34dc33d48c
commit
a6ad4cf48c
2 changed files with 101 additions and 23 deletions
76
tx/tx.go
76
tx/tx.go
|
@ -44,11 +44,13 @@ type UtxoStore struct {
|
||||||
|
|
||||||
type Utxo struct {
|
type Utxo struct {
|
||||||
Addr [ripemd160.Size]byte
|
Addr [ripemd160.Size]byte
|
||||||
TxHash btcwire.ShaHash
|
Out OutPoint
|
||||||
Amt int64 // Measured in Satoshis
|
Amt int64 // Measured in Satoshis
|
||||||
Height int64
|
Height int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OutPoint btcwire.OutPoint
|
||||||
|
|
||||||
// TxStore is a slice holding RecvTx and SendTx pointers.
|
// TxStore is a slice holding RecvTx and SendTx pointers.
|
||||||
type TxStore []interface{}
|
type TxStore []interface{}
|
||||||
|
|
||||||
|
@ -176,17 +178,71 @@ func (u *UtxoStore) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
// ReadFrom satisifies the io.ReaderFrom interface. A Utxo is read
|
// ReadFrom satisifies the io.ReaderFrom interface. A Utxo is read
|
||||||
// from r with the format:
|
// from r with the format:
|
||||||
//
|
//
|
||||||
// [TxHash (32 bytes), Amt (8 bytes), Height (8 bytes)]
|
// [Addr (20 bytes), Out (36 bytes), Amt (8 bytes), Height (8 bytes)]
|
||||||
//
|
//
|
||||||
// Each field is read little endian.
|
// Each field is read little endian.
|
||||||
func (u *Utxo) ReadFrom(r io.Reader) (n int64, err error) {
|
func (u *Utxo) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
datas := []interface{}{
|
datas := []interface{}{
|
||||||
&u.Addr,
|
&u.Addr,
|
||||||
&u.TxHash,
|
&u.Out,
|
||||||
&u.Amt,
|
&u.Amt,
|
||||||
&u.Height,
|
&u.Height,
|
||||||
}
|
}
|
||||||
var read int64
|
var read int64
|
||||||
|
for _, data := range datas {
|
||||||
|
if rf, ok := data.(io.ReaderFrom); ok {
|
||||||
|
read, err = rf.ReadFrom(r)
|
||||||
|
} else {
|
||||||
|
read, err = binaryRead(r, binary.LittleEndian, data)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return n + read, err
|
||||||
|
}
|
||||||
|
n += read
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteTo satisifies the io.WriterTo interface. A Utxo is written to
|
||||||
|
// w in the format:
|
||||||
|
//
|
||||||
|
// [Addr (20 bytes), Out (36 bytes), Amt (8 bytes), Height (8 bytes)]
|
||||||
|
//
|
||||||
|
// Each field is written little endian.
|
||||||
|
func (u *Utxo) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
|
datas := []interface{}{
|
||||||
|
&u.Addr,
|
||||||
|
&u.Out,
|
||||||
|
&u.Amt,
|
||||||
|
&u.Height,
|
||||||
|
}
|
||||||
|
var written int64
|
||||||
|
for _, data := range datas {
|
||||||
|
if wt, ok := data.(io.WriterTo); ok {
|
||||||
|
written, err = wt.WriteTo(w)
|
||||||
|
} else {
|
||||||
|
written, err = binaryWrite(w, binary.LittleEndian, data)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return n + written, err
|
||||||
|
}
|
||||||
|
n += written
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadFrom satisifies the io.ReaderFrom interface. A OutPoint is read
|
||||||
|
// from r with the format:
|
||||||
|
//
|
||||||
|
// [Hash (32 bytes), Index (4 bytes)]
|
||||||
|
//
|
||||||
|
// Each field is read little endian.
|
||||||
|
func (o *OutPoint) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
|
datas := []interface{}{
|
||||||
|
&o.Hash,
|
||||||
|
&o.Index,
|
||||||
|
}
|
||||||
|
var read int64
|
||||||
for _, data := range datas {
|
for _, data := range datas {
|
||||||
read, err = binaryRead(r, binary.LittleEndian, data)
|
read, err = binaryRead(r, binary.LittleEndian, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -197,18 +253,16 @@ func (u *Utxo) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
return n, nil
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteTo satisifies the io.WriterTo interface. A Utxo is written to
|
// WriteTo satisifies the io.WriterTo interface. A OutPoit is written
|
||||||
// w in the format:
|
// to w in the format:
|
||||||
//
|
//
|
||||||
// [TxHash (32 bytes), Amt (8 bytes), Height (8 bytes)]
|
// [Hash (32 bytes), Index (4 bytes)]
|
||||||
//
|
//
|
||||||
// Each field is written little endian.
|
// Each field is written little endian.
|
||||||
func (u *Utxo) WriteTo(w io.Writer) (n int64, err error) {
|
func (o *OutPoint) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
datas := []interface{}{
|
datas := []interface{}{
|
||||||
&u.Addr,
|
&o.Hash,
|
||||||
&u.TxHash,
|
&o.Index,
|
||||||
&u.Amt,
|
|
||||||
&u.Height,
|
|
||||||
}
|
}
|
||||||
var written int64
|
var written int64
|
||||||
for _, data := range datas {
|
for _, data := range datas {
|
||||||
|
|
|
@ -91,10 +91,13 @@ func TestUtxoWriteRead(t *testing.T) {
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||||
16, 17, 18, 19,
|
16, 17, 18, 19,
|
||||||
},
|
},
|
||||||
TxHash: [btcwire.HashSize]byte{
|
Out: OutPoint{
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
Hash: [btcwire.HashSize]byte{
|
||||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||||
30, 31,
|
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
|
||||||
|
30, 31,
|
||||||
|
},
|
||||||
|
Index: 1,
|
||||||
},
|
},
|
||||||
Amt: 69,
|
Amt: 69,
|
||||||
Height: 1337,
|
Height: 1337,
|
||||||
|
@ -139,20 +142,22 @@ func TestUtxoStoreWriteRead(t *testing.T) {
|
||||||
store1 := new(UtxoStore)
|
store1 := new(UtxoStore)
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
utxo := new(Utxo)
|
utxo := new(Utxo)
|
||||||
for j, _ := range utxo.TxHash[:] {
|
for j, _ := range utxo.Out.Hash[:] {
|
||||||
utxo.TxHash[j] = byte(i)
|
utxo.Out.Hash[j] = byte(i)
|
||||||
}
|
}
|
||||||
utxo.Amt = int64(i + 1)
|
utxo.Out.Index = uint32(i + 1)
|
||||||
utxo.Height = int64(i + 2)
|
utxo.Amt = int64(i + 2)
|
||||||
|
utxo.Height = int64(i + 3)
|
||||||
store1.Confirmed = append(store1.Confirmed, utxo)
|
store1.Confirmed = append(store1.Confirmed, utxo)
|
||||||
}
|
}
|
||||||
for i := 10; i < 20; i++ {
|
for i := 10; i < 20; i++ {
|
||||||
utxo := new(Utxo)
|
utxo := new(Utxo)
|
||||||
for j, _ := range utxo.TxHash[:] {
|
for j, _ := range utxo.Out.Hash[:] {
|
||||||
utxo.TxHash[j] = byte(i)
|
utxo.Out.Hash[j] = byte(i)
|
||||||
}
|
}
|
||||||
utxo.Amt = int64(i + 1)
|
utxo.Out.Index = uint32(i + 1)
|
||||||
utxo.Height = int64(i + 2)
|
utxo.Amt = int64(i + 2)
|
||||||
|
utxo.Height = int64(i + 3)
|
||||||
store1.Unconfirmed = append(store1.Unconfirmed, utxo)
|
store1.Unconfirmed = append(store1.Unconfirmed, utxo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,9 +202,11 @@ func TestRecvTxWriteRead(t *testing.T) {
|
||||||
n, err := recvtx.WriteTo(bufWriter)
|
n, err := recvtx.WriteTo(bufWriter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if int(n) != binary.Size(recvtx) {
|
if int(n) != binary.Size(recvtx) {
|
||||||
t.Error("Writing Tx: Size Mismatch")
|
t.Error("Writing Tx: Size Mismatch")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
txBytes := bufWriter.Bytes()
|
txBytes := bufWriter.Bytes()
|
||||||
|
|
||||||
|
@ -207,13 +214,16 @@ func TestRecvTxWriteRead(t *testing.T) {
|
||||||
n, err = tx.ReadFrom(bytes.NewBuffer(txBytes))
|
n, err = tx.ReadFrom(bytes.NewBuffer(txBytes))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if int(n) != binary.Size(tx) {
|
if int(n) != binary.Size(tx) {
|
||||||
t.Error("Reading Tx: Size Mismatch")
|
t.Error("Reading Tx: Size Mismatch")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(recvtx, tx) {
|
if !reflect.DeepEqual(recvtx, tx) {
|
||||||
t.Error("Txs do not match.")
|
t.Error("Txs do not match.")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
truncatedReadBuf := bytes.NewBuffer(txBytes)
|
truncatedReadBuf := bytes.NewBuffer(txBytes)
|
||||||
|
@ -221,9 +231,11 @@ func TestRecvTxWriteRead(t *testing.T) {
|
||||||
n, err = tx.ReadFrom(truncatedReadBuf)
|
n, err = tx.ReadFrom(truncatedReadBuf)
|
||||||
if err != io.EOF {
|
if err != io.EOF {
|
||||||
t.Error("Expected err = io.EOF reading from truncated buffer.")
|
t.Error("Expected err = io.EOF reading from truncated buffer.")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if n != btcwire.HashSize {
|
if n != btcwire.HashSize {
|
||||||
t.Error("Incorrect number of bytes read from truncated buffer.")
|
t.Error("Incorrect number of bytes read from truncated buffer.")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,6 +244,7 @@ func TestSendTxWriteRead(t *testing.T) {
|
||||||
n1, err := sendtx.WriteTo(bufWriter)
|
n1, err := sendtx.WriteTo(bufWriter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
txBytes := bufWriter.Bytes()
|
txBytes := bufWriter.Bytes()
|
||||||
|
|
||||||
|
@ -239,13 +252,16 @@ func TestSendTxWriteRead(t *testing.T) {
|
||||||
n2, err := tx.ReadFrom(bytes.NewBuffer(txBytes))
|
n2, err := tx.ReadFrom(bytes.NewBuffer(txBytes))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if n1 != n2 {
|
if n1 != n2 {
|
||||||
t.Error("Number of bytes written and read mismatch.")
|
t.Error("Number of bytes written and read mismatch.")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(sendtx, tx) {
|
if !reflect.DeepEqual(sendtx, tx) {
|
||||||
t.Error("Txs do not match.")
|
t.Error("Txs do not match.")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
truncatedReadBuf := bytes.NewBuffer(txBytes)
|
truncatedReadBuf := bytes.NewBuffer(txBytes)
|
||||||
|
@ -253,9 +269,11 @@ func TestSendTxWriteRead(t *testing.T) {
|
||||||
n, err := tx.ReadFrom(truncatedReadBuf)
|
n, err := tx.ReadFrom(truncatedReadBuf)
|
||||||
if err != io.EOF {
|
if err != io.EOF {
|
||||||
t.Error("Expected err = io.EOF reading from truncated buffer.")
|
t.Error("Expected err = io.EOF reading from truncated buffer.")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if n != btcwire.HashSize {
|
if n != btcwire.HashSize {
|
||||||
t.Error("Incorrect number of bytes read from truncated buffer.")
|
t.Error("Incorrect number of bytes read from truncated buffer.")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,6 +285,7 @@ func TestTxStoreWriteRead(t *testing.T) {
|
||||||
n1, err := store.WriteTo(bufWriter)
|
n1, err := store.WriteTo(bufWriter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
txsBytes := bufWriter.Bytes()
|
txsBytes := bufWriter.Bytes()
|
||||||
|
|
||||||
|
@ -274,14 +293,17 @@ func TestTxStoreWriteRead(t *testing.T) {
|
||||||
n2, err := txs.ReadFrom(bytes.NewBuffer(txsBytes))
|
n2, err := txs.ReadFrom(bytes.NewBuffer(txsBytes))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if n1 != n2 {
|
if n1 != n2 {
|
||||||
t.Error("Number of bytes written and read mismatch.")
|
t.Error("Number of bytes written and read mismatch.")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(store, txs) {
|
if !reflect.DeepEqual(store, txs) {
|
||||||
spew.Dump(store, txs)
|
spew.Dump(store, txs)
|
||||||
t.Error("TxStores do not match.")
|
t.Error("TxStores do not match.")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
truncatedReadBuf := bytes.NewBuffer(txsBytes)
|
truncatedReadBuf := bytes.NewBuffer(txsBytes)
|
||||||
|
@ -289,8 +311,10 @@ func TestTxStoreWriteRead(t *testing.T) {
|
||||||
n, err := txs.ReadFrom(truncatedReadBuf)
|
n, err := txs.ReadFrom(truncatedReadBuf)
|
||||||
if err != io.EOF {
|
if err != io.EOF {
|
||||||
t.Error("Expected err = io.EOF reading from truncated buffer.")
|
t.Error("Expected err = io.EOF reading from truncated buffer.")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if n != 50 {
|
if n != 50 {
|
||||||
t.Error("Incorrect number of bytes read from truncated buffer.")
|
t.Error("Incorrect number of bytes read from truncated buffer.")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue