Skip to content

Commit d3a8469

Browse files
authored
feat: generate Handshake TX hash (#332)
Signed-off-by: Aurora Gaffney <[email protected]>
1 parent c8eb3c0 commit d3a8469

File tree

3 files changed

+90
-17
lines changed

3 files changed

+90
-17
lines changed

internal/handshake/block.go

+18-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
package handshake
88

99
import (
10+
"bytes"
1011
"encoding/binary"
1112
"io"
1213
)
@@ -16,13 +17,28 @@ type Block struct {
1617
Transactions []Transaction
1718
}
1819

19-
func (b *Block) Decode(r io.Reader) error {
20+
func NewBlockFromReader(r io.Reader) (*Block, error) {
21+
// Read entire input into a bytes.Buffer
22+
tmpData, err := io.ReadAll(r)
23+
if err != nil {
24+
return nil, err
25+
}
26+
buf := bytes.NewBuffer(tmpData)
27+
// Decode block
28+
var tmpBlock Block
29+
if err := tmpBlock.Decode(buf); err != nil {
30+
return nil, err
31+
}
32+
return &tmpBlock, err
33+
}
34+
35+
func (b *Block) Decode(r *bytes.Buffer) error {
2036
// Decode header
2137
if err := b.Header.Decode(r); err != nil {
2238
return err
2339
}
2440
// Transactions
25-
txCount, err := binary.ReadUvarint(r.(io.ByteReader))
41+
txCount, err := binary.ReadUvarint(r)
2642
if err != nil {
2743
return err
2844
}

internal/handshake/block_test.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,7 @@ func TestDecodeHandshakeBlock(t *testing.T) {
164164
t.Fatalf("unexpected error: %s", err)
165165
}
166166
br := bytes.NewReader(testBlockBytes)
167-
var block handshake.Block
168-
err = block.Decode(br)
167+
block, err := handshake.NewBlockFromReader(br)
169168
if err != nil {
170169
t.Fatalf("unexpected error deserializing block: %s", err)
171170
}

internal/handshake/transaction.go

+71-13
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,49 @@
77
package handshake
88

99
import (
10+
"bytes"
1011
"encoding/binary"
1112
"errors"
1213
"io"
14+
15+
"golang.org/x/crypto/blake2b"
1316
)
1417

1518
type Transaction struct {
16-
Version uint32
17-
Inputs []TransactionInput
18-
Outputs []TransactionOutput
19-
LockTime uint32
19+
Version uint32
20+
Inputs []TransactionInput
21+
Outputs []TransactionOutput
22+
LockTime uint32
23+
hash []byte
24+
witnessHash []byte
2025
}
2126

22-
func (t *Transaction) Decode(r io.Reader) error {
23-
var err error
24-
if err = binary.Read(r, binary.LittleEndian, &t.Version); err != nil {
27+
func NewTransactionFromReader(r io.Reader) (*Transaction, error) {
28+
// Read entire input into a bytes.Buffer
29+
tmpData, err := io.ReadAll(r)
30+
if err != nil {
31+
return nil, err
32+
}
33+
buf := bytes.NewBuffer(tmpData)
34+
// Decode TX
35+
var tmpTransaction Transaction
36+
if err := tmpTransaction.Decode(buf); err != nil {
37+
return nil, err
38+
}
39+
return &tmpTransaction, err
40+
}
41+
42+
func (t *Transaction) Decode(r *bytes.Buffer) error {
43+
// Save original buffer
44+
// This is needed to capture TX bytes
45+
origData := make([]byte, r.Len())
46+
copy(origData, r.Bytes())
47+
// Version
48+
if err := binary.Read(r, binary.LittleEndian, &t.Version); err != nil {
2549
return err
2650
}
2751
// Inputs
28-
inCount, err := binary.ReadUvarint(r.(io.ByteReader))
52+
inCount, err := binary.ReadUvarint(r)
2953
if err != nil {
3054
return err
3155
}
@@ -37,7 +61,7 @@ func (t *Transaction) Decode(r io.Reader) error {
3761
t.Inputs = append(t.Inputs, tmpInput)
3862
}
3963
// Outputs
40-
outCount, err := binary.ReadUvarint(r.(io.ByteReader))
64+
outCount, err := binary.ReadUvarint(r)
4165
if err != nil {
4266
return err
4367
}
@@ -52,22 +76,56 @@ func (t *Transaction) Decode(r io.Reader) error {
5276
if err := binary.Read(r, binary.LittleEndian, &t.LockTime); err != nil {
5377
return err
5478
}
79+
// Capture original TX bytes
80+
txBytes := origData[:len(origData)-r.Len()]
81+
// Generate TX hash
82+
tmpHash := blake2b.Sum256(txBytes)
83+
t.hash = make([]byte, len(tmpHash))
84+
copy(t.hash, tmpHash[:])
85+
// Save remaining data
86+
// This is needed for capturing the witness data bytes
87+
origData = make([]byte, r.Len())
88+
copy(origData, r.Bytes())
5589
// Witnesses
5690
for i := uint64(0); i < inCount; i++ {
5791
if err := t.Inputs[i].DecodeWitness(r); err != nil {
5892
return err
5993
}
6094
}
95+
// Capture original bytes for witness data
96+
witnessDataBytes := origData[:len(origData)-r.Len()]
97+
// Generate witness data hash
98+
witnessDataHash := blake2b.Sum256(witnessDataBytes)
99+
// Generate TX hash with witness data
100+
h, err := blake2b.New256(nil)
101+
if err != nil {
102+
return err
103+
}
104+
h.Write(t.hash)
105+
h.Write(witnessDataHash[:])
106+
t.witnessHash = h.Sum(nil)
61107
return nil
62108
}
63109

110+
func (t *Transaction) Hash() []byte {
111+
ret := make([]byte, len(t.hash))
112+
copy(ret, t.hash)
113+
return ret
114+
}
115+
116+
func (t *Transaction) WitnessHash() []byte {
117+
ret := make([]byte, len(t.witnessHash))
118+
copy(ret, t.witnessHash)
119+
return ret
120+
}
121+
64122
type TransactionInput struct {
65123
PrevOutpoint Outpoint
66124
Sequence uint32
67125
Witness [][]byte
68126
}
69127

70-
func (i *TransactionInput) Decode(r io.Reader) error {
128+
func (i *TransactionInput) Decode(r *bytes.Buffer) error {
71129
if err := i.PrevOutpoint.Decode(r); err != nil {
72130
return err
73131
}
@@ -102,7 +160,7 @@ type TransactionOutput struct {
102160
Covenant GenericCovenant
103161
}
104162

105-
func (o *TransactionOutput) Decode(r io.Reader) error {
163+
func (o *TransactionOutput) Decode(r *bytes.Buffer) error {
106164
if err := binary.Read(r, binary.LittleEndian, &o.Value); err != nil {
107165
return err
108166
}
@@ -120,7 +178,7 @@ type Outpoint struct {
120178
Index uint32
121179
}
122180

123-
func (o *Outpoint) Decode(r io.Reader) error {
181+
func (o *Outpoint) Decode(r *bytes.Buffer) error {
124182
return binary.Read(r, binary.LittleEndian, o)
125183
}
126184

@@ -129,7 +187,7 @@ type Address struct {
129187
Hash []byte
130188
}
131189

132-
func (a *Address) Decode(r io.Reader) error {
190+
func (a *Address) Decode(r *bytes.Buffer) error {
133191
if err := binary.Read(r, binary.LittleEndian, &a.Version); err != nil {
134192
return err
135193
}

0 commit comments

Comments
 (0)