Save the pkScript for each Utxo. This is needed to create transactions.
This commit is contained in:
parent
24d6168709
commit
fa85e586fc
2 changed files with 79 additions and 29 deletions
72
tx/tx.go
72
tx/tx.go
|
@ -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++ {
|
||||||
|
|
|
@ -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.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue