Save the pkScript for each Utxo. This is needed to create transactions.

This commit is contained in:
Josh Rickmar 2013-09-09 13:31:37 -04:00
parent 24d6168709
commit fa85e586fc
2 changed files with 79 additions and 29 deletions

View file

@ -44,19 +44,22 @@ type UtxoStore struct {
type Utxo struct { type Utxo struct {
Addr [ripemd160.Size]byte Addr [ripemd160.Size]byte
Out OutPoint Out OutPoint
Amt int64 // Measured in Satoshis Subscript PKScript
Amt uint64 // Measured in Satoshis
Height int64 Height int64
} }
type OutPoint btcwire.OutPoint type OutPoint btcwire.OutPoint
type PKScript []byte
// TxStore is a slice holding RecvTx and SendTx pointers. // TxStore is a slice holding RecvTx and SendTx pointers.
type TxStore []interface{} type TxStore []interface{}
type RecvTx struct { type RecvTx struct {
TxHash btcwire.ShaHash TxHash btcwire.ShaHash
Amt int64 // Measured in Satoshis Amt uint64 // Measured in Satoshis
SenderAddr [ripemd160.Size]byte SenderAddr [ripemd160.Size]byte
ReceiverAddr [ripemd160.Size]byte ReceiverAddr [ripemd160.Size]byte
} }
@ -67,7 +70,7 @@ type SendTx struct {
SenderAddr [ripemd160.Size]byte SenderAddr [ripemd160.Size]byte
ReceiverAddrs []struct { ReceiverAddrs []struct {
Addr [ripemd160.Size]byte Addr [ripemd160.Size]byte
Amt int64 // Measured in Satoshis Amt uint64 // Measured in Satoshis
} }
} }
@ -178,13 +181,14 @@ 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:
// //
// [Addr (20 bytes), Out (36 bytes), Amt (8 bytes), Height (8 bytes)] // [Addr (20 bytes), Out (36 bytes), Subscript (varies), 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.Out, &u.Out,
&u.Subscript,
&u.Amt, &u.Amt,
&u.Height, &u.Height,
} }
@ -206,13 +210,14 @@ func (u *Utxo) ReadFrom(r io.Reader) (n int64, err error) {
// WriteTo satisifies the io.WriterTo interface. A Utxo is written to // WriteTo satisifies the io.WriterTo interface. A Utxo is written to
// w in the format: // w in the format:
// //
// [Addr (20 bytes), Out (36 bytes), Amt (8 bytes), Height (8 bytes)] // [Addr (20 bytes), Out (36 bytes), Subscript (varies), Amt (8 bytes), Height (8 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 (u *Utxo) WriteTo(w io.Writer) (n int64, err error) {
datas := []interface{}{ datas := []interface{}{
&u.Addr, &u.Addr,
&u.Out, &u.Out,
&u.Subscript,
&u.Amt, &u.Amt,
&u.Height, &u.Height,
} }
@ -231,7 +236,7 @@ func (u *Utxo) WriteTo(w io.Writer) (n int64, err error) {
return n, nil return n, nil
} }
// ReadFrom satisifies the io.ReaderFrom interface. A OutPoint is read // ReadFrom satisifies the io.ReaderFrom interface. An OutPoint is read
// from r with the format: // from r with the format:
// //
// [Hash (32 bytes), Index (4 bytes)] // [Hash (32 bytes), Index (4 bytes)]
@ -253,7 +258,7 @@ func (o *OutPoint) ReadFrom(r io.Reader) (n int64, err error) {
return n, nil return n, nil
} }
// WriteTo satisifies the io.WriterTo interface. A OutPoit is written // WriteTo satisifies the io.WriterTo interface. An OutPoint is written
// to w in the format: // to w in the format:
// //
// [Hash (32 bytes), Index (4 bytes)] // [Hash (32 bytes), Index (4 bytes)]
@ -275,6 +280,55 @@ func (o *OutPoint) WriteTo(w io.Writer) (n int64, err error) {
return n, nil return n, nil
} }
// ReadFrom satisifies the io.ReaderFrom interface. A PKScript is read
// from r with the format:
//
// [Length (4 byte unsigned integer), ScriptBytes (Length bytes)]
//
// Length is read little endian.
func (s *PKScript) ReadFrom(r io.Reader) (n int64, err error) {
var scriptlen uint32
var read int64
read, err = binaryRead(r, binary.LittleEndian, &scriptlen)
if err != nil {
return n + read, err
}
n += read
scriptbuf := new(bytes.Buffer)
read, err = scriptbuf.ReadFrom(io.LimitReader(r, int64(scriptlen)))
if err != nil {
return n + read, err
}
n += read
*s = scriptbuf.Bytes()
return n, nil
}
// WriteTo satisifies the io.WriterTo interface. A PKScript is written
// to w in the format:
//
// [Length (4 byte unsigned integer), ScriptBytes (Length bytes)]
//
// Length is written little endian.
func (s *PKScript) WriteTo(w io.Writer) (n int64, err error) {
var written int64
written, err = binaryWrite(w, binary.LittleEndian, uint32(len(*s)))
if err != nil {
return n + written, nil
}
n += written
written, err = bytes.NewBuffer(*s).WriteTo(w)
if err != nil {
return n + written, nil
}
n += written
return n, nil
}
// ReadFrom satisifies the io.ReaderFrom interface. A TxStore is read // ReadFrom satisifies the io.ReaderFrom interface. A TxStore is read
// in from r with the format: // in from r with the format:
// //
@ -430,7 +484,7 @@ func (tx *SendTx) ReadFrom(r io.Reader) (n int64, err error) {
tx.ReceiverAddrs = make([]struct { tx.ReceiverAddrs = make([]struct {
Addr [ripemd160.Size]byte Addr [ripemd160.Size]byte
Amt int64 Amt uint64
}, },
nReceivers) nReceivers)
for i := uint32(0); i < nReceivers; i++ { for i := uint32(0); i < nReceivers; i++ {

View file

@ -28,8 +28,6 @@ import (
) )
var ( var (
utxoByteSize = binary.Size(Utxo{})
recvtx = &RecvTx{ recvtx = &RecvTx{
TxHash: [btcwire.HashSize]byte{ TxHash: [btcwire.HashSize]byte{
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,
@ -59,11 +57,11 @@ var (
}, },
ReceiverAddrs: []struct { ReceiverAddrs: []struct {
Addr [ripemd160.Size]byte Addr [ripemd160.Size]byte
Amt int64 Amt uint64
}{ }{
struct { struct {
Addr [ripemd160.Size]byte Addr [ripemd160.Size]byte
Amt int64 Amt uint64
}{ }{
Amt: 69, Amt: 69,
Addr: [ripemd160.Size]byte{ Addr: [ripemd160.Size]byte{
@ -73,7 +71,7 @@ var (
}, },
struct { struct {
Addr [ripemd160.Size]byte Addr [ripemd160.Size]byte
Amt int64 Amt uint64
}{ }{
Amt: 96, Amt: 96,
Addr: [ripemd160.Size]byte{ Addr: [ripemd160.Size]byte{
@ -99,26 +97,24 @@ func TestUtxoWriteRead(t *testing.T) {
}, },
Index: 1, Index: 1,
}, },
Subscript: []byte{},
Amt: 69, Amt: 69,
Height: 1337, Height: 1337,
} }
bufWriter := &bytes.Buffer{} bufWriter := &bytes.Buffer{}
n, err := utxo1.WriteTo(bufWriter) written, err := utxo1.WriteTo(bufWriter)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
if int(n) != binary.Size(utxo1) {
t.Error("Writing Utxo: Size Mismatch")
}
utxoBytes := bufWriter.Bytes() utxoBytes := bufWriter.Bytes()
utxo2 := new(Utxo) utxo2 := new(Utxo)
n, err = utxo2.ReadFrom(bytes.NewBuffer(utxoBytes)) read, err := utxo2.ReadFrom(bytes.NewBuffer(utxoBytes))
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
if int(n) != binary.Size(utxo2) { if written != read {
t.Error("Reading Utxo: Size Mismatch") t.Error("Reading and Writing Utxo: Size Mismatch")
} }
if !reflect.DeepEqual(utxo1, utxo2) { if !reflect.DeepEqual(utxo1, utxo2) {
@ -129,7 +125,7 @@ func TestUtxoWriteRead(t *testing.T) {
truncatedReadBuf := bytes.NewBuffer(utxoBytes) truncatedReadBuf := bytes.NewBuffer(utxoBytes)
truncatedReadBuf.Truncate(btcwire.HashSize) truncatedReadBuf.Truncate(btcwire.HashSize)
utxo3 := new(Utxo) utxo3 := new(Utxo)
n, err = utxo3.ReadFrom(truncatedReadBuf) n, err := utxo3.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.")
} }
@ -146,7 +142,8 @@ func TestUtxoStoreWriteRead(t *testing.T) {
utxo.Out.Hash[j] = byte(i) utxo.Out.Hash[j] = byte(i)
} }
utxo.Out.Index = uint32(i + 1) utxo.Out.Index = uint32(i + 1)
utxo.Amt = int64(i + 2) utxo.Subscript = []byte{}
utxo.Amt = uint64(i + 2)
utxo.Height = int64(i + 3) utxo.Height = int64(i + 3)
store1.Confirmed = append(store1.Confirmed, utxo) store1.Confirmed = append(store1.Confirmed, utxo)
} }
@ -156,7 +153,8 @@ func TestUtxoStoreWriteRead(t *testing.T) {
utxo.Out.Hash[j] = byte(i) utxo.Out.Hash[j] = byte(i)
} }
utxo.Out.Index = uint32(i + 1) utxo.Out.Index = uint32(i + 1)
utxo.Amt = int64(i + 2) utxo.Subscript = []byte{}
utxo.Amt = uint64(i + 2)
utxo.Height = int64(i + 3) utxo.Height = int64(i + 3)
store1.Unconfirmed = append(store1.Unconfirmed, utxo) store1.Unconfirmed = append(store1.Unconfirmed, utxo)
} }
@ -166,9 +164,6 @@ func TestUtxoStoreWriteRead(t *testing.T) {
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
if n != 20*(1+int64(utxoByteSize)) {
t.Error("Incorrect number of bytes written.")
}
storeBytes := bufWriter.Bytes() storeBytes := bufWriter.Bytes()
@ -182,17 +177,18 @@ func TestUtxoStoreWriteRead(t *testing.T) {
} }
if !reflect.DeepEqual(store1, store2) { if !reflect.DeepEqual(store1, store2) {
spew.Dump(store1, store2)
t.Error("Stores do not match.") t.Error("Stores do not match.")
} }
truncatedReadBuf := bytes.NewBuffer(storeBytes) truncatedReadBuf := bytes.NewBuffer(storeBytes)
truncatedReadBuf.Truncate(10*(1+utxoByteSize) + btcwire.HashSize) truncatedReadBuf.Truncate(100)
store3 := new(UtxoStore) store3 := new(UtxoStore)
n, err = store3.ReadFrom(truncatedReadBuf) n, err = store3.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.")
} }
if n != 10*(1+int64(utxoByteSize))+btcwire.HashSize { if n != 100 {
t.Error("Incorrect number of bytes read from truncated buffer.") t.Error("Incorrect number of bytes read from truncated buffer.")
} }
} }