@@ -57,14 +57,15 @@ uint32_t transaction::subscript_v1(const script& script) NOEXCEPT
57
57
// ext_flags and annex flag are combined into one byte, who knows why.
58
58
uint8_t transaction::spend_type_v1 (bool annex, bool tapscript) const NOEXCEPT
59
59
{
60
- const auto ext_flags = to_value (tapscript ?
61
- extension::tapscript : extension:: taproot);
60
+ const auto ext_flag = to_value (tapscript ? extension::tapscript :
61
+ extension::taproot);
62
62
63
- return set_right (shift_left (ext_flags ), zero, annex);
63
+ return set_right (shift_left (ext_flag ), zero, annex);
64
64
}
65
65
66
66
// NOT THREAD SAFE
67
67
// Concurrent input validation for a tx unsafe due to on-demand hash caching.
68
+ // TODO: may be more optimal to not cache single output hash as use is rare.
68
69
bool transaction::version1_sighash (hash_digest& out,
69
70
const input_iterator& input, const script& script, uint64_t value,
70
71
const hash_cptr& tapleaf, uint8_t sighash_flags) const NOEXCEPT
@@ -80,6 +81,18 @@ bool transaction::version1_sighash(hash_digest& out,
80
81
const auto single = (flag == coverage::hash_single);
81
82
const auto all = (flag == coverage::hash_all);
82
83
84
+ // ************************************************************************
85
+ // CONSENSUS: Guards public interface only, node always populates prevout.
86
+ // ************************************************************************
87
+ if (anyone && is_null (in.prevout ))
88
+ return false ;
89
+
90
+ // ************************************************************************
91
+ // CONSENSUS: Taproot finally eliminates one_hash (null_hash in v0) return.
92
+ // ************************************************************************
93
+ if (single && output_overflow (input_index (input)))
94
+ return false ;
95
+
83
96
// Create tagged hash writer.
84
97
stream::out::fast stream{ out };
85
98
hash::sha256t::fast<" TapSighash" > sink{ stream };
@@ -106,10 +119,6 @@ bool transaction::version1_sighash(hash_digest& out,
106
119
107
120
if (anyone)
108
121
{
109
- // This implies a parameterization error, and will fail the script.
110
- if (is_null (in.prevout ))
111
- return false ;
112
-
113
122
in.point ().to_data (sink);
114
123
sink.write_8_bytes_little_endian (value);
115
124
in.prevout ->script ().to_data (sink, true );
@@ -122,19 +131,13 @@ bool transaction::version1_sighash(hash_digest& out,
122
131
123
132
if (annex)
124
133
{
125
- sink.write_variable (annex.size ());
126
- sink.write_bytes (annex.hash ());
134
+ sink.write_bytes (annex.hash (true ));
127
135
}
128
136
129
137
if (single)
130
138
{
131
- const auto index = input_index (input);
132
- if (output_overflow (index))
133
- return false ;
134
-
135
139
// Hash is cached for use with each single sigop in the same script.
136
- // TODO: it may be more optimal to not cache, since benefit is rare.
137
- sink.write_bytes (outputs_->at (index)->get_hash ());
140
+ sink.write_bytes (outputs_->at (input_index (input))->get_hash ());
138
141
}
139
142
140
143
// Additional for tapscript [bip342].
@@ -146,11 +149,6 @@ bool transaction::version1_sighash(hash_digest& out,
146
149
sink.write_4_bytes_little_endian (subscript_v1 (script));
147
150
}
148
151
149
- // TODO: write position pertains to the hash instance (written at flush).
150
- // Total length at most 206 bytes (!anyone, no epoch/tapscript) [bip341].
151
- // //BC_ASSERT(!anyone && sink.get_write_position() == (add1(206u) + 37));
152
- // //BC_ASSERT( anyone && sink.get_write_position() == (add1(157u) + 37));
153
-
154
152
sink.flush ();
155
153
return true ;
156
154
}
0 commit comments