Skip to content

Commit 90cae04

Browse files
committed
Use is_sighash_valid in sigops, bit_and, add/use is_anyone_can_pay().
1 parent c73ad0e commit 90cae04

File tree

5 files changed

+80
-32
lines changed

5 files changed

+80
-32
lines changed

include/bitcoin/system/chain/transaction.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ class BC_API transaction
255255
} sighash_cache;
256256

257257
static inline coverage mask_sighash(uint8_t sighash_flags) NOEXCEPT;
258-
static inline bool is_sighash_valid(uint8_t sighash_flags) NOEXCEPT;
258+
static inline bool is_anyone_can_pay(uint8_t sighash_flags) NOEXCEPT;
259259

260260
// delegated
261261
code connect_input(const context& ctx,

include/bitcoin/system/impl/machine/program.ipp

+26-4
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,30 @@ ops_increment(size_t public_keys) NOEXCEPT
751751
// Endorsement parsing.
752752
// ----------------------------------------------------------------------------
753753

754+
// static
755+
// BIP341: Using any undefined hash_type causes validation failure if violated.
756+
// defined types: 0x00, 0x01, 0x02, 0x03, 0x81, 0x82, or 0x83. [zero is the
757+
// default and cannot be explicit, but is serialized for signature hashing].
758+
TEMPLATE
759+
inline bool CLASS::
760+
is_valid_sighash_byte(uint8_t sighash_flags) NOEXCEPT
761+
{
762+
switch (sighash_flags)
763+
{
764+
// BIP341: zero is invalid sighash, must be explicit to prevent mally.
765+
////case coverage::hash_default:
766+
case coverage::hash_all:
767+
case coverage::hash_none:
768+
case coverage::hash_single:
769+
case coverage::all_anyone_can_pay:
770+
case coverage::none_anyone_can_pay:
771+
case coverage::single_anyone_can_pay:
772+
return true;
773+
default:
774+
return false;
775+
}
776+
}
777+
754778
// static
755779
TEMPLATE
756780
inline data_slice CLASS::
@@ -770,6 +794,7 @@ schnorr_split(uint8_t& sighash_flags, const data_chunk& endorsement) NOEXCEPT
770794
{
771795
using namespace chain;
772796
using namespace schnorr;
797+
sighash_flags = coverage::invalid;
773798
const auto size = endorsement.size();
774799

775800
if (size == signature_size)
@@ -782,17 +807,14 @@ schnorr_split(uint8_t& sighash_flags, const data_chunk& endorsement) NOEXCEPT
782807
{
783808
// BIP341: signature has sighash byte appended in the usual fashion.
784809
const auto byte = endorsement.back();
785-
786-
// BIP341: zero is invalid sighash, must be explicit to prevent mally.
787-
if (is_nonzero(byte))
810+
if (is_valid_sighash_byte(byte))
788811
sighash_flags = byte;
789812
}
790813
else
791814
{
792815
// This makes an invalid return safe to dereference, and may be
793816
// compiled out unless a caller does in fact access it.
794817
static constexpr ec_signature empty{};
795-
sighash_flags = coverage::invalid;
796818
return empty;
797819
}
798820

include/bitcoin/system/machine/program.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ class program
197197
private:
198198
using primary_stack = stack<Stack>;
199199
static constexpr auto bip342_mask = bit_not<uint32_t>(flags::bip342_rule);
200+
static inline bool is_valid_sighash_byte(uint8_t sighash_flags) NOEXCEPT;
200201
static inline uint32_t subscript(const chain::script& script) NOEXCEPT;
201202
static inline chain::strippers create_strip_ops(
202203
const chunk_xptrs& endorsements) NOEXCEPT;

src/chain/transaction.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,9 @@ uint64_t transaction::fee() const NOEXCEPT
351351
return floored_subtract(value(), claim());
352352
}
353353

354+
// Hashing.
355+
// ----------------------------------------------------------------------------
356+
354357
void transaction::set_nominal_hash(const hash_digest& hash) const NOEXCEPT
355358
{
356359
nominal_hash_ = hash;

src/chain/transaction_sign.cpp

+49-27
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ uint32_t transaction::input_index(const input_iterator& input) const NOEXCEPT
144144
//*****************************************************************************
145145
inline coverage transaction::mask_sighash(uint8_t sighash_flags) NOEXCEPT
146146
{
147-
switch (sighash_flags & coverage::mask)
147+
switch (bit_and<uint8_t>(sighash_flags, coverage::mask))
148148
{
149149
case coverage::hash_single:
150150
return coverage::hash_single;
@@ -155,6 +155,11 @@ inline coverage transaction::mask_sighash(uint8_t sighash_flags) NOEXCEPT
155155
}
156156
}
157157

158+
inline bool transaction::is_anyone_can_pay(uint8_t sighash_flags) NOEXCEPT
159+
{
160+
return to_bool(bit_and<uint8_t>(sighash_flags, coverage::anyone_can_pay));
161+
}
162+
158163
// ****************************************************************************
159164
// CONSENSUS: sighash flags are carried in a single byte but are encoded as 4
160165
// bytes in the signature hash preimage serialization.
@@ -167,8 +172,8 @@ void transaction::signature_hash_single(writer& sink,
167172
const auto write_inputs = [this, &input, &subscript, sighash_flags](
168173
writer& sink) NOEXCEPT
169174
{
170-
const auto anyone = to_bool(sighash_flags & coverage::anyone_can_pay);
171175
input_cptrs::const_iterator in;
176+
const auto anyone = is_anyone_can_pay(sighash_flags);
172177

173178
sink.write_variable(anyone ? one : inputs_->size());
174179

@@ -218,8 +223,8 @@ void transaction::signature_hash_none(writer& sink,
218223
const auto write_inputs = [this, &input, &subscript, sighash_flags](
219224
writer& sink) NOEXCEPT
220225
{
221-
const auto anyone = to_bool(sighash_flags & coverage::anyone_can_pay);
222226
input_cptrs::const_iterator in;
227+
const auto anyone = is_anyone_can_pay(sighash_flags);
223228

224229
sink.write_variable(anyone ? one : inputs_->size());
225230

@@ -256,8 +261,8 @@ void transaction::signature_hash_all(writer& sink,
256261
const auto write_inputs = [this, &input, &subscript, sighash_flags](
257262
writer& sink) NOEXCEPT
258263
{
259-
const auto anyone = to_bool(sighash_flags & coverage::anyone_can_pay);
260264
input_cptrs::const_iterator in;
265+
const auto anyone = is_anyone_can_pay(sighash_flags);
261266

262267
sink.write_variable(anyone ? one : inputs_->size());
263268

@@ -380,7 +385,7 @@ hash_digest transaction::version_0_sighash(const input_iterator& input,
380385
uint8_t sighash_flags) const NOEXCEPT
381386
{
382387
// Set options.
383-
const auto anyone = to_bool(sighash_flags & coverage::anyone_can_pay);
388+
const auto anyone = is_anyone_can_pay(sighash_flags);
384389
const auto flag = mask_sighash(sighash_flags);
385390
const auto all = (flag == coverage::hash_all);
386391
const auto single = (flag == coverage::hash_single);
@@ -427,31 +432,48 @@ hash_digest transaction::version_0_sighash(const input_iterator& input,
427432
// Because the codeseparator_position is the last input to the hash, the SHA256
428433
// midstate can be efficiently cached for multiple OP_CODESEPARATOR in a script.
429434

430-
// static
431-
// BIP341: Using any undefined hash_type causes validation failure if violated.
432-
// defined types: 0x00, 0x01, 0x02, 0x03, 0x81, 0x82, or 0x83. [zero is the
433-
// default and cannot be explicit, but is serialized for signature hashing.
434-
inline bool transaction::is_sighash_valid(uint8_t sighash_flags) NOEXCEPT
435-
{
436-
switch (sighash_flags)
437-
{
438-
case coverage::hash_default:
439-
case coverage::hash_all:
440-
case coverage::hash_none:
441-
case coverage::hash_single:
442-
case coverage::all_anyone_can_pay:
443-
case coverage::none_anyone_can_pay:
444-
case coverage::single_anyone_can_pay:
445-
return true;
446-
default:
447-
return false;
448-
}
449-
}
450-
451435
hash_digest transaction::version_1_sighash(const input_iterator& input,
452436
const script& script, uint64_t value, uint8_t sighash_flags) const NOEXCEPT
453437
{
454-
return {};
438+
// Set options.
439+
const auto anyone = is_anyone_can_pay(sighash_flags);
440+
const auto flag = mask_sighash(sighash_flags);
441+
const auto all = (flag == coverage::hash_all);
442+
const auto single = (flag == coverage::hash_single);
443+
444+
// Create hash writer.
445+
hash_digest digest{};
446+
stream::out::fast stream{ digest };
447+
hash::sha256x2::fast sink{ stream };
448+
449+
// Create signature hash.
450+
sink.write_little_endian(version_);
451+
452+
// Conditioning points, sequences, and outputs writes on cache_ instead of
453+
// conditionally passing them from methods avoids copying the cached hash.
454+
455+
// points
456+
sink.write_bytes(!anyone ? points_hash() : null_hash);
457+
458+
// sequences
459+
sink.write_bytes(!anyone && all ? sequences_hash() : null_hash);
460+
461+
(*input)->point().to_data(sink);
462+
script.to_data(sink, prefixed);
463+
sink.write_little_endian(value);
464+
sink.write_little_endian((*input)->sequence());
465+
466+
// outputs
467+
if (single)
468+
sink.write_bytes(output_hash(input));
469+
else
470+
sink.write_bytes(all ? outputs_hash() : null_hash);
471+
472+
sink.write_little_endian(locktime_);
473+
sink.write_4_bytes_little_endian(sighash_flags);
474+
475+
sink.flush();
476+
return digest;
455477
}
456478

457479
} // namespace chain

0 commit comments

Comments
 (0)