Skip to content

Commit 1a17713

Browse files
committed
tx: implement (caching) segwit v0/bip143 signature hashing
Share parameter checking code between bip143/bip431, and reject all-zero genesis hashes in the signing code itself.
1 parent b2da197 commit 1a17713

File tree

1 file changed

+154
-36
lines changed

1 file changed

+154
-36
lines changed

src/tx_io.c

Lines changed: 154 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
#define TXIO_SHA_OUTPUT_WITNESSES_D (TXIO_SHA_OUTPUTS | TXIO_SHA256_D)
3838
/* ... end of segwit cached data */
3939

40+
static const unsigned char zero_hash[SHA256_LEN];
41+
4042
/* SHA256(TapSighash) */
4143
static const unsigned char TAPSIGHASH_SHA256[SHA256_LEN] = {
4244
0xf4, 0x0a, 0x48, 0xdf, 0x4b, 0x2a, 0x70, 0xc8, 0xb4, 0x92, 0x4b, 0xf2, 0x65, 0x46, 0x61, 0xed,
@@ -555,6 +557,107 @@ static void txio_hash_tapleaf_hash(cursor_io *io,
555557
}
556558
}
557559

560+
/* BIP 143 */
561+
static int bip143_signature_hash(
562+
const struct wally_tx *tx, size_t index,
563+
const struct wally_map *values,
564+
const unsigned char *scriptcode, size_t scriptcode_len,
565+
uint32_t sighash,
566+
struct wally_map *cache,
567+
bool is_elements,
568+
unsigned char *bytes_out, size_t len)
569+
{
570+
const struct wally_tx_input *txin = tx ? tx->inputs + index : NULL;
571+
const struct wally_tx_output *txout = tx ? tx->outputs + index : NULL;
572+
const bool sh_anyonecanpay = sighash & WALLY_SIGHASH_ANYONECANPAY;
573+
#ifdef BUILD_ELEMENTS
574+
const bool sh_rangeproof = sighash & WALLY_SIGHASH_RANGEPROOF;
575+
#endif
576+
const bool sh_none = (sighash & WALLY_SIGHASH_MASK) == WALLY_SIGHASH_NONE;
577+
const bool sh_single = (sighash & WALLY_SIGHASH_MASK) == WALLY_SIGHASH_SINGLE;
578+
cursor_io io;
579+
580+
/* Note that scriptcode can be empty, so we don't check it here */
581+
if (!tx || !values || BYTES_INVALID(scriptcode, scriptcode_len) ||
582+
sighash & 0xffffff00)
583+
return WALLY_EINVAL;
584+
585+
{
586+
/* Validate input values: We must have the value at 'index'. */
587+
bool (*value_len_fn)(size_t) = is_elements ? value_len_ok : satoshi_len_ok;
588+
if (!map_has_one(values, index, value_len_fn))
589+
return WALLY_EINVAL;
590+
}
591+
592+
/* Init */
593+
io.cache = cache;
594+
io.cursor = bytes_out;
595+
io.max = len;
596+
sha256_init(&io.ctx);
597+
/* Tx data */
598+
hash_le32(&io.ctx, tx->version);
599+
if (sh_anyonecanpay)
600+
hash_bytes(&io.ctx, zero_hash, sizeof(zero_hash));
601+
else
602+
txio_hash_sha_prevouts(&io, tx, TXIO_SHA_PREVOUTS_D);
603+
if (sh_anyonecanpay || sh_single || sh_none)
604+
hash_bytes(&io.ctx, zero_hash, sizeof(zero_hash));
605+
else
606+
txio_hash_sha_sequences(&io, tx, TXIO_SHA_SEQUENCES_D);
607+
#ifdef BUILD_ELEMENTS
608+
if (is_elements) {
609+
if (sh_anyonecanpay)
610+
hash_bytes(&io.ctx, zero_hash, sizeof(zero_hash));
611+
else
612+
txio_hash_sha_issuances(&io, tx, TXIO_SHA_ISSUANCES_D);
613+
}
614+
#endif
615+
/* Input data */
616+
txio_hash_outpoint(&io, txin);
617+
#ifdef BUILD_ELEMENTS
618+
if (is_elements)
619+
txio_hash_input_elements(&io, tx, index, NULL, NULL, values,
620+
scriptcode, scriptcode_len, WALLY_SIGTYPE_SW_V0);
621+
else
622+
#endif
623+
txio_hash_input(&io, tx, index, NULL, values,
624+
scriptcode, scriptcode_len, WALLY_SIGTYPE_SW_V0);
625+
626+
/* Output data */
627+
if (sh_none || (sh_single && index >= tx->num_outputs))
628+
hash_bytes(&io.ctx, zero_hash, sizeof(zero_hash));
629+
else if (sh_single) {
630+
#ifdef BUILD_ELEMENTS
631+
if (is_elements)
632+
txio_hash_sha_single_output_elements(&io, txout, TXIO_UNCACHED_D);
633+
else
634+
#endif
635+
txio_hash_sha_single_output(&io, txout, TXIO_UNCACHED_D);
636+
} else {
637+
#ifdef BUILD_ELEMENTS
638+
if (is_elements)
639+
txio_hash_sha_outputs_elements(&io, tx, TXIO_SHA_OUTPUTS_D);
640+
else
641+
#endif
642+
txio_hash_sha_outputs(&io, tx, TXIO_SHA_OUTPUTS_D);
643+
}
644+
645+
#ifdef BUILD_ELEMENTS
646+
if (sh_rangeproof) {
647+
if (sh_none || (sh_single && index >= tx->num_outputs))
648+
hash_bytes(&io.ctx, zero_hash, sizeof(zero_hash));
649+
else if (sh_single)
650+
txio_hash_sha_single_output_witness(&io, txout, TXIO_UNCACHED_D);
651+
else
652+
txio_hash_sha_output_witnesses(&io, tx, TXIO_SHA_OUTPUT_WITNESSES_D);
653+
}
654+
#endif
655+
656+
hash_le32(&io.ctx, tx->locktime);
657+
hash_le32(&io.ctx, sighash);
658+
return txio_done(&io, TXIO_SHA256_D);
659+
}
660+
558661
/* BIP 341 */
559662
static void txio_bip341_init(cursor_io *io,
560663
const unsigned char *genesis_blockhash, size_t genesis_blockhash_len)
@@ -612,18 +715,12 @@ static int bip341_signature_hash(
612715
const bool sh_anyprevout_anyscript = bip341_is_input_hash_type(sighash, WALLY_SIGHASH_ANYPREVOUTANYSCRIPT);
613716
cursor_io io;
614717

615-
if (!tx || index >= tx->num_inputs ||
616-
!values ||
617-
BYTES_INVALID(tapleaf_script, tapleaf_script_len) ||
618-
key_version > 1 ||
619-
codesep_position != WALLY_NO_CODESEPARATOR || /* TODO: Add support */
620-
BYTES_INVALID(annex, annex_len) || (annex && *annex != 0x50) ||
621-
BYTES_INVALID_N(genesis_blockhash, genesis_blockhash_len, SHA256_LEN) ||
622-
!bytes_out || len != SHA256_LEN)
623-
return WALLY_EINVAL;
718+
if (index >= tx->num_inputs || (annex && *annex != 0x50))
719+
return WALLY_EINVAL;
624720

625721
if (is_elements) {
626-
if (!genesis_blockhash)
722+
if (!genesis_blockhash ||
723+
mem_is_zero(genesis_blockhash, genesis_blockhash_len))
627724
return WALLY_EINVAL;
628725
} else {
629726
genesis_blockhash = NULL;
@@ -653,30 +750,6 @@ static int bip341_signature_hash(
653750
return WALLY_EINVAL;
654751
}
655752

656-
switch (sighash) {
657-
case WALLY_SIGHASH_DEFAULT:
658-
case WALLY_SIGHASH_ALL:
659-
case WALLY_SIGHASH_NONE:
660-
case WALLY_SIGHASH_SINGLE:
661-
case WALLY_SIGHASH_ALL | WALLY_SIGHASH_ANYONECANPAY:
662-
case WALLY_SIGHASH_NONE | WALLY_SIGHASH_ANYONECANPAY:
663-
case WALLY_SIGHASH_SINGLE | WALLY_SIGHASH_ANYONECANPAY:
664-
break; /* Always valid */
665-
case WALLY_SIGHASH_ALL | WALLY_SIGHASH_ANYPREVOUT:
666-
case WALLY_SIGHASH_NONE | WALLY_SIGHASH_ANYPREVOUT:
667-
case WALLY_SIGHASH_SINGLE | WALLY_SIGHASH_ANYPREVOUT:
668-
case WALLY_SIGHASH_ALL | WALLY_SIGHASH_ANYPREVOUT | WALLY_SIGHASH_ANYONECANPAY:
669-
case WALLY_SIGHASH_NONE | WALLY_SIGHASH_ANYPREVOUT | WALLY_SIGHASH_ANYONECANPAY:
670-
case WALLY_SIGHASH_SINGLE | WALLY_SIGHASH_ANYPREVOUT | WALLY_SIGHASH_ANYONECANPAY:
671-
if (key_version != 1)
672-
return WALLY_EINVAL; /* Only valid for key_version 1 */
673-
if (is_elements)
674-
return WALLY_ERROR; /* Elements: unsure of Activation status/no ELIP */
675-
break;
676-
default:
677-
return WALLY_EINVAL; /* Unknown sighash type */
678-
}
679-
680753
/* Init */
681754
io.cache = cache;
682755
io.cursor = bytes_out;
@@ -782,15 +855,60 @@ int wally_tx_get_input_signature_hash(
782855
uint32_t sighash_type = flags & WALLY_SIGTYPE_MASK;
783856
int ret = WALLY_EINVAL;
784857

785-
if (!flags || (flags & ~SIGTYPE_ALL))
858+
if (!tx || !tx->num_inputs || !tx->num_outputs || !values ||
859+
BYTES_INVALID(tapleaf_script, tapleaf_script_len) ||
860+
key_version > 1 ||
861+
codesep_position != WALLY_NO_CODESEPARATOR || /* TODO: Add support */
862+
BYTES_INVALID(annex, annex_len) ||
863+
BYTES_INVALID_N(genesis_blockhash, genesis_blockhash_len, SHA256_LEN) ||
864+
!flags || (flags & ~SIGTYPE_ALL) || !bytes_out || len != SHA256_LEN)
786865
return WALLY_EINVAL;
787866

788867
#ifdef BUILD_ELEMENTS
789868
if ((ret = wally_tx_is_elements(tx, &is_elements)) != WALLY_OK)
790869
return ret;
791870
#endif
792871

793-
/* FIXME: Support segwit/pre-segwit hashing */
872+
switch (sighash) {
873+
case WALLY_SIGHASH_DEFAULT:
874+
#if 0
875+
/* TODO: The previous impl allows a sighash of 0 for
876+
* pre-segwit/segwit v0 txs. We should probably disallow this.
877+
*/
878+
if (sighash_type != WALLY_SIGTYPE_SW_V1)
879+
return WALLY_EINVAL; /* Only valid for taproot */
880+
break;
881+
#endif
882+
case WALLY_SIGHASH_ALL:
883+
case WALLY_SIGHASH_NONE:
884+
case WALLY_SIGHASH_SINGLE:
885+
case WALLY_SIGHASH_ALL | WALLY_SIGHASH_ANYONECANPAY:
886+
case WALLY_SIGHASH_NONE | WALLY_SIGHASH_ANYONECANPAY:
887+
case WALLY_SIGHASH_SINGLE | WALLY_SIGHASH_ANYONECANPAY:
888+
break; /* Always valid */
889+
case WALLY_SIGHASH_ALL | WALLY_SIGHASH_ANYPREVOUT:
890+
case WALLY_SIGHASH_NONE | WALLY_SIGHASH_ANYPREVOUT:
891+
case WALLY_SIGHASH_SINGLE | WALLY_SIGHASH_ANYPREVOUT:
892+
case WALLY_SIGHASH_ALL | WALLY_SIGHASH_ANYPREVOUT | WALLY_SIGHASH_ANYONECANPAY:
893+
case WALLY_SIGHASH_NONE | WALLY_SIGHASH_ANYPREVOUT | WALLY_SIGHASH_ANYONECANPAY:
894+
case WALLY_SIGHASH_SINGLE | WALLY_SIGHASH_ANYPREVOUT | WALLY_SIGHASH_ANYONECANPAY:
895+
if (sighash_type != WALLY_SIGTYPE_SW_V1 || key_version != 1)
896+
return WALLY_EINVAL; /* Only valid for taproot key version 1 */
897+
if (is_elements) {
898+
/* Activation status unclear and no ELIP: disallow for now */
899+
return WALLY_ERROR;
900+
}
901+
break;
902+
default:
903+
return WALLY_EINVAL; /* Unknown sighash type */
904+
}
905+
906+
/* FIXME: Support pre-segwit hashing */
907+
if (sighash_type == WALLY_SIGTYPE_SW_V0)
908+
return bip143_signature_hash(tx, index, values,
909+
tapleaf_script, tapleaf_script_len,
910+
sighash, cache, is_elements,
911+
bytes_out, len);
794912
if (sighash_type == WALLY_SIGTYPE_SW_V1)
795913
return bip341_signature_hash(tx, index, scripts, assets, values,
796914
tapleaf_script, tapleaf_script_len,

0 commit comments

Comments
 (0)