@@ -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 );
@@ -127,13 +136,8 @@ bool transaction::version1_sighash(hash_digest& out,
127
136
128
137
if (single)
129
138
{
130
- const auto index = input_index (input);
131
- if (output_overflow (index))
132
- return false ;
133
-
134
139
// Hash is cached for use with each single sigop in the same script.
135
- // TODO: it may be more optimal to not cache, since benefit is rare.
136
- sink.write_bytes (outputs_->at (index)->get_hash ());
140
+ sink.write_bytes (outputs_->at (input_index (input))->get_hash ());
137
141
}
138
142
139
143
// Additional for tapscript [bip342].
@@ -145,11 +149,6 @@ bool transaction::version1_sighash(hash_digest& out,
145
149
sink.write_4_bytes_little_endian (subscript_v1 (script));
146
150
}
147
151
148
- // TODO: write position pertains to the hash instance (written at flush).
149
- // Total length at most 206 bytes (!anyone, no epoch/tapscript) [bip341].
150
- // //BC_ASSERT(!anyone && sink.get_write_position() == (add1(206u) + 37));
151
- // //BC_ASSERT( anyone && sink.get_write_position() == (add1(157u) + 37));
152
-
153
152
sink.flush ();
154
153
return true ;
155
154
}
0 commit comments