7
7
package handshake
8
8
9
9
import (
10
+ "bytes"
10
11
"encoding/binary"
11
12
"errors"
12
13
"io"
14
+
15
+ "golang.org/x/crypto/blake2b"
13
16
)
14
17
15
18
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
20
25
}
21
26
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 {
25
49
return err
26
50
}
27
51
// Inputs
28
- inCount , err := binary .ReadUvarint (r .(io. ByteReader ) )
52
+ inCount , err := binary .ReadUvarint (r )
29
53
if err != nil {
30
54
return err
31
55
}
@@ -37,7 +61,7 @@ func (t *Transaction) Decode(r io.Reader) error {
37
61
t .Inputs = append (t .Inputs , tmpInput )
38
62
}
39
63
// Outputs
40
- outCount , err := binary .ReadUvarint (r .(io. ByteReader ) )
64
+ outCount , err := binary .ReadUvarint (r )
41
65
if err != nil {
42
66
return err
43
67
}
@@ -52,22 +76,56 @@ func (t *Transaction) Decode(r io.Reader) error {
52
76
if err := binary .Read (r , binary .LittleEndian , & t .LockTime ); err != nil {
53
77
return err
54
78
}
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 ())
55
89
// Witnesses
56
90
for i := uint64 (0 ); i < inCount ; i ++ {
57
91
if err := t .Inputs [i ].DecodeWitness (r ); err != nil {
58
92
return err
59
93
}
60
94
}
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 )
61
107
return nil
62
108
}
63
109
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
+
64
122
type TransactionInput struct {
65
123
PrevOutpoint Outpoint
66
124
Sequence uint32
67
125
Witness [][]byte
68
126
}
69
127
70
- func (i * TransactionInput ) Decode (r io. Reader ) error {
128
+ func (i * TransactionInput ) Decode (r * bytes. Buffer ) error {
71
129
if err := i .PrevOutpoint .Decode (r ); err != nil {
72
130
return err
73
131
}
@@ -102,7 +160,7 @@ type TransactionOutput struct {
102
160
Covenant GenericCovenant
103
161
}
104
162
105
- func (o * TransactionOutput ) Decode (r io. Reader ) error {
163
+ func (o * TransactionOutput ) Decode (r * bytes. Buffer ) error {
106
164
if err := binary .Read (r , binary .LittleEndian , & o .Value ); err != nil {
107
165
return err
108
166
}
@@ -120,7 +178,7 @@ type Outpoint struct {
120
178
Index uint32
121
179
}
122
180
123
- func (o * Outpoint ) Decode (r io. Reader ) error {
181
+ func (o * Outpoint ) Decode (r * bytes. Buffer ) error {
124
182
return binary .Read (r , binary .LittleEndian , o )
125
183
}
126
184
@@ -129,7 +187,7 @@ type Address struct {
129
187
Hash []byte
130
188
}
131
189
132
- func (a * Address ) Decode (r io. Reader ) error {
190
+ func (a * Address ) Decode (r * bytes. Buffer ) error {
133
191
if err := binary .Read (r , binary .LittleEndian , & a .Version ); err != nil {
134
192
return err
135
193
}
0 commit comments