Skip to content

Commit ad42a96

Browse files
committed
tx: migrate bip143 signature hashing to the new impl
Note the indentation of the existing (no pre-segwit-only) impl is not changed, since this makes the diff smaller, and it too will be migrated in a future commit.
1 parent 1a17713 commit ad42a96

File tree

1 file changed

+35
-278
lines changed

1 file changed

+35
-278
lines changed

src/transaction.c

Lines changed: 35 additions & 278 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ struct tx_serialize_opts
4343
const unsigned char *script; /* scriptPubkey spent by the input we are signing */
4444
size_t script_len; /* length of 'script' in bytes */
4545
uint64_t satoshi; /* Amount of the input we are signing */
46-
bool bip143; /* Serialize for BIP143 hash */
4746
const unsigned char *value; /* Confidential value of the input we are signing */
4847
size_t value_len; /* length of 'value' in bytes */
4948
};
@@ -1720,37 +1719,7 @@ static int tx_get_lengths(const struct wally_tx *tx,
17201719

17211720
if (opts) {
17221721
if (flags & WALLY_TX_FLAG_USE_WITNESS)
1723-
return WALLY_ERROR; /* Segwit tx hashing uses bip143 opts member */
1724-
1725-
if (opts->bip143) {
1726-
size_t issuance_size, amount_size = sizeof(uint64_t);
1727-
1728-
*base_size = sizeof(uint32_t) + /* version */
1729-
SHA256_LEN + /* hash prevouts */
1730-
SHA256_LEN + /* hash sequence */
1731-
WALLY_TXHASH_LEN + sizeof(uint32_t) + /* outpoint + index */
1732-
varbuff_get_length(opts->script_len) + /* script */
1733-
sizeof(uint32_t) + /* input sequence */
1734-
SHA256_LEN + /* hash outputs */
1735-
(sh_rangeproof ? SHA256_LEN : 0) + /* rangeproof */
1736-
sizeof(uint32_t) + /* nlocktime */
1737-
sizeof(uint32_t); /* tx sighash */
1738-
1739-
if (is_elements) {
1740-
/* Amount, possibly blinded */
1741-
if (!(amount_size = confidential_value_length_from_bytes(opts->value)))
1742-
return WALLY_EINVAL;
1743-
amount_size += SHA256_LEN; /* TODO: Comment what this represents */
1744-
}
1745-
*base_size += amount_size;
1746-
1747-
if (get_txin_issuance_size(tx->inputs + opts->index,
1748-
&issuance_size, NULL) != WALLY_OK)
1749-
return WALLY_EINVAL;
1750-
*base_size += issuance_size;
1751-
*witness_size = 0;
1752-
return WALLY_OK;
1753-
}
1722+
return WALLY_ERROR; /* Segwit tx hashing done elsewhere */
17541723
}
17551724

17561725
if ((flags & ~WALLY_TX_ALL_FLAGS) ||
@@ -2048,233 +2017,6 @@ int wally_tx_get_hash_prevouts(const struct wally_tx *tx,
20482017
return hash_prevouts(buff_p, inputs_size, bytes_out, len, inputs_size > sizeof(buff));
20492018
}
20502019

2051-
static int tx_to_bip143_bytes(const struct wally_tx *tx,
2052-
const struct tx_serialize_opts *opts,
2053-
uint32_t flags,
2054-
unsigned char *bytes_out, size_t len,
2055-
size_t *written)
2056-
{
2057-
unsigned char buff[TX_STACK_SIZE / 2], *buff_p = buff;
2058-
size_t i, inputs_size, outputs_size, rangeproof_size = 0, issuances_size = 0, buff_len = sizeof(buff);
2059-
size_t is_elements = 0;
2060-
const unsigned char sighash = opts->sighash;
2061-
const bool sh_anyonecanpay = sighash & WALLY_SIGHASH_ANYONECANPAY;
2062-
const bool sh_rangeproof = sighash & WALLY_SIGHASH_RANGEPROOF;
2063-
const bool sh_none = (sighash & WALLY_SIGHASH_MASK) == WALLY_SIGHASH_NONE;
2064-
const bool sh_single = (sighash & WALLY_SIGHASH_MASK) == WALLY_SIGHASH_SINGLE;
2065-
unsigned char *p = bytes_out, *output_p;
2066-
int ret = WALLY_OK;
2067-
2068-
(void)flags;
2069-
(void)len;
2070-
(void)sh_rangeproof;
2071-
2072-
#ifdef BUILD_ELEMENTS
2073-
if ((ret = wally_tx_is_elements(tx, &is_elements)) != WALLY_OK)
2074-
return ret;
2075-
#endif
2076-
2077-
/* Note we assume tx_to_bytes has already validated all inputs */
2078-
p += uint32_to_le_bytes(tx->version, p);
2079-
2080-
inputs_size = tx->num_inputs * (WALLY_TXHASH_LEN + sizeof(uint32_t));
2081-
if (sh_none || (sh_single && opts->index >= tx->num_outputs))
2082-
outputs_size = 0;
2083-
else if (sh_single) {
2084-
const struct wally_tx_output *output = tx->outputs + opts->index;
2085-
size_t wit_size = 0, *wit_p = sh_rangeproof ? &wit_size : NULL;
2086-
outputs_size = txout_get_serialized_len(output, is_elements, wit_p);
2087-
if (!outputs_size)
2088-
goto error; /* Error getting txout length */
2089-
rangeproof_size += wit_size;
2090-
} else {
2091-
outputs_size = 0;
2092-
for (i = 0; i < tx->num_outputs; ++i) {
2093-
const struct wally_tx_output *output = tx->outputs + i;
2094-
size_t wit_size = 0, *wit_p = sh_rangeproof ? &wit_size : NULL;
2095-
size_t n = txout_get_serialized_len(output, is_elements, wit_p);
2096-
if (!n)
2097-
goto error; /* Error getting txout length */
2098-
outputs_size += n;
2099-
rangeproof_size += wit_size;
2100-
}
2101-
}
2102-
2103-
#ifdef BUILD_ELEMENTS
2104-
if (is_elements && !sh_anyonecanpay) {
2105-
for (i = 0; i < tx->num_inputs; ++i) {
2106-
if (tx->inputs[i].features & WALLY_TX_IS_ISSUANCE) {
2107-
size_t issuance_size;
2108-
if (get_txin_issuance_size(tx->inputs + i,
2109-
&issuance_size, NULL) != WALLY_OK)
2110-
return WALLY_EINVAL;
2111-
issuances_size += issuance_size;
2112-
} else
2113-
issuances_size += 1;
2114-
}
2115-
}
2116-
#endif /* BUILD_ELEMENTS */
2117-
2118-
if (inputs_size > buff_len || outputs_size > buff_len ||
2119-
rangeproof_size > buff_len || issuances_size > buff_len) {
2120-
buff_len = inputs_size > outputs_size ? inputs_size : outputs_size;
2121-
buff_len = buff_len > rangeproof_size ? buff_len : rangeproof_size;
2122-
buff_len = buff_len > issuances_size ? buff_len : issuances_size;
2123-
buff_p = wally_malloc(buff_len);
2124-
if (buff_p == NULL)
2125-
return WALLY_ENOMEM;
2126-
}
2127-
2128-
/* Inputs */
2129-
if (sh_anyonecanpay)
2130-
memset(p, 0, SHA256_LEN);
2131-
else {
2132-
for (i = 0; i < tx->num_inputs; ++i) {
2133-
unsigned char *tmp_p = buff_p + i * (WALLY_TXHASH_LEN + sizeof(uint32_t));
2134-
memcpy(tmp_p, tx->inputs[i].txhash, WALLY_TXHASH_LEN);
2135-
uint32_to_le_bytes(tx->inputs[i].index, tmp_p + WALLY_TXHASH_LEN);
2136-
}
2137-
2138-
if ((ret = wally_sha256d(buff_p, inputs_size, p, SHA256_LEN)) != WALLY_OK)
2139-
goto error;
2140-
}
2141-
p += SHA256_LEN;
2142-
2143-
/* Sequences */
2144-
if (sh_anyonecanpay || sh_single || sh_none)
2145-
memset(p, 0, SHA256_LEN);
2146-
else {
2147-
for (i = 0; i < tx->num_inputs; ++i)
2148-
uint32_to_le_bytes(tx->inputs[i].sequence, buff_p + i * sizeof(uint32_t));
2149-
2150-
ret = wally_sha256d(buff_p, tx->num_inputs * sizeof(uint32_t), p, SHA256_LEN);
2151-
if (ret != WALLY_OK)
2152-
goto error;
2153-
}
2154-
p += SHA256_LEN;
2155-
2156-
#ifdef BUILD_ELEMENTS
2157-
if (is_elements) {
2158-
/* sha_issuances */
2159-
if (sh_anyonecanpay)
2160-
memset(p, 0, SHA256_LEN);
2161-
else {
2162-
unsigned char *tmp_p = buff_p;
2163-
for (i = 0; i < tx->num_inputs; ++i) {
2164-
if (tx->inputs[i].features & WALLY_TX_IS_ISSUANCE) {
2165-
memcpy(tmp_p, tx->inputs[i].blinding_nonce, SHA256_LEN);
2166-
tmp_p += SHA256_LEN;
2167-
memcpy(tmp_p, tx->inputs[i].entropy, SHA256_LEN);
2168-
tmp_p += SHA256_LEN;
2169-
tmp_p += confidential_value_to_bytes(tx->inputs[i].issuance_amount,
2170-
tx->inputs[i].issuance_amount_len, tmp_p);
2171-
tmp_p += confidential_value_to_bytes(tx->inputs[i].inflation_keys,
2172-
tx->inputs[i].inflation_keys_len, tmp_p);
2173-
}
2174-
else
2175-
*tmp_p++ = 0;
2176-
}
2177-
2178-
if ((ret = wally_sha256d(buff_p, issuances_size, p, SHA256_LEN)) != WALLY_OK)
2179-
goto error;
2180-
}
2181-
p += SHA256_LEN;
2182-
}
2183-
#endif /* BUILD_ELEMENTS */
2184-
2185-
/* Input details */
2186-
memcpy(p, tx->inputs[opts->index].txhash, WALLY_TXHASH_LEN);
2187-
p += WALLY_TXHASH_LEN;
2188-
p += uint32_to_le_bytes(tx->inputs[opts->index].index, p);
2189-
p += varbuff_to_bytes(opts->script, opts->script_len, p);
2190-
if (!is_elements)
2191-
p += uint64_to_le_bytes(opts->satoshi, p);
2192-
#ifdef BUILD_ELEMENTS
2193-
else
2194-
p += confidential_value_to_bytes(opts->value, opts->value_len, p);
2195-
#endif
2196-
p += uint32_to_le_bytes(tx->inputs[opts->index].sequence, p);
2197-
2198-
#ifdef BUILD_ELEMENTS
2199-
if (is_elements && (tx->inputs[opts->index].features & WALLY_TX_IS_ISSUANCE)) {
2200-
memcpy(p, tx->inputs[opts->index].blinding_nonce, SHA256_LEN);
2201-
p += SHA256_LEN;
2202-
memcpy(p, tx->inputs[opts->index].entropy, SHA256_LEN);
2203-
p += SHA256_LEN;
2204-
p += confidential_value_to_bytes(tx->inputs[opts->index].issuance_amount,
2205-
tx->inputs[opts->index].issuance_amount_len, p);
2206-
p += confidential_value_to_bytes(tx->inputs[opts->index].inflation_keys,
2207-
tx->inputs[opts->index].inflation_keys_len, p);
2208-
}
2209-
#endif
2210-
2211-
/* Outputs */
2212-
if (sh_none || (sh_single && opts->index >= tx->num_outputs))
2213-
memset(p, 0, SHA256_LEN);
2214-
else {
2215-
output_p = buff_p;
2216-
for (i = 0; i < tx->num_outputs; ++i) {
2217-
if (sh_single && i != opts->index)
2218-
continue;
2219-
if (!is_elements)
2220-
output_p += uint64_to_le_bytes(tx->outputs[i].satoshi, output_p);
2221-
#ifdef BUILD_ELEMENTS
2222-
else {
2223-
output_p += confidential_value_to_bytes(tx->outputs[i].asset, tx->outputs[i].asset_len,
2224-
output_p);
2225-
output_p += confidential_value_to_bytes(tx->outputs[i].value, tx->outputs[i].value_len,
2226-
output_p);
2227-
output_p += confidential_value_to_bytes(tx->outputs[i].nonce, tx->outputs[i].nonce_len,
2228-
output_p);
2229-
}
2230-
#endif
2231-
output_p += varbuff_to_bytes(tx->outputs[i].script,
2232-
tx->outputs[i].script_len, output_p);
2233-
}
2234-
2235-
ret = wally_sha256d(buff_p, outputs_size, p, SHA256_LEN);
2236-
if (ret != WALLY_OK)
2237-
goto error;
2238-
}
2239-
p += SHA256_LEN;
2240-
2241-
/* rangeproof */
2242-
#ifdef BUILD_ELEMENTS
2243-
if (is_elements && sh_rangeproof) {
2244-
if (sh_none || (sh_single && opts->index >= tx->num_outputs))
2245-
memset(p, 0, SHA256_LEN);
2246-
else {
2247-
output_p = buff_p;
2248-
for (i = 0; i < tx->num_outputs; ++i) {
2249-
if (sh_single && i != opts->index)
2250-
continue;
2251-
output_p += varbuff_to_bytes(tx->outputs[i].rangeproof,
2252-
tx->outputs[i].rangeproof_len, output_p);
2253-
output_p += varbuff_to_bytes(tx->outputs[i].surjectionproof,
2254-
tx->outputs[i].surjectionproof_len, output_p);
2255-
}
2256-
ret = wally_sha256d(buff_p, rangeproof_size, p, SHA256_LEN);
2257-
if (ret != WALLY_OK)
2258-
goto error;
2259-
}
2260-
p += SHA256_LEN;
2261-
}
2262-
#endif
2263-
2264-
/* nlocktime and sighash*/
2265-
p += uint32_to_le_bytes(tx->locktime, p);
2266-
p += uint32_to_le_bytes(opts->tx_sighash, p);
2267-
2268-
*written = p - bytes_out;
2269-
2270-
error:
2271-
if (buff_p != buff)
2272-
clear_and_free(buff_p, buff_len);
2273-
else
2274-
wally_clear(buff, sizeof(buff));
2275-
return ret;
2276-
}
2277-
22782020
static int tx_to_bytes(const struct wally_tx *tx,
22792021
const struct tx_serialize_opts *opts,
22802022
uint32_t flags,
@@ -2324,9 +2066,6 @@ static int tx_to_bytes(const struct wally_tx *tx,
23242066
return WALLY_OK;
23252067
}
23262068

2327-
if (opts && opts->bip143)
2328-
return tx_to_bip143_bytes(tx, opts, flags, bytes_out, len, written);
2329-
23302069
if (flags & WALLY_TX_FLAG_USE_WITNESS) {
23312070
if (wally_tx_get_witness_count(tx, &witness_count) != WALLY_OK)
23322071
return WALLY_EINVAL;
@@ -2993,14 +2732,41 @@ static int tx_get_signature_hash(const struct wally_tx *tx,
29932732
uint32_t sighash, uint32_t tx_sighash, uint32_t flags,
29942733
unsigned char *bytes_out, size_t len)
29952734
{
2735+
size_t is_elements = 0;
2736+
2737+
#ifdef BUILD_ELEMENTS
2738+
if (wally_tx_is_elements(tx, &is_elements) != WALLY_OK)
2739+
return WALLY_EINVAL;
2740+
#endif
2741+
2742+
if (extra || extra_len || extra_offset)
2743+
return WALLY_ERROR; /* Not implemented, not planned */
2744+
2745+
if (flags & WALLY_TX_FLAG_USE_WITNESS) {
2746+
struct wally_map_item value_item;
2747+
struct wally_map values = { &value_item, 1, 1, NULL };
2748+
values.items[0].key = NULL;
2749+
values.items[0].key_len = index;
2750+
if (is_elements) {
2751+
value_item.value = (unsigned char*)value;
2752+
value_item.value_len = value_len;
2753+
} else {
2754+
value_item.value = (unsigned char*)&satoshi;
2755+
value_item.value_len = sizeof(uint64_t);
2756+
}
2757+
return wally_tx_get_input_signature_hash(tx, index, NULL, NULL,
2758+
&values, script, script_len,
2759+
0, WALLY_NO_CODESEPARATOR,
2760+
NULL, 0, NULL, 0,
2761+
sighash, WALLY_SIGTYPE_SW_V0,
2762+
NULL, bytes_out, len);
2763+
} else {
29962764
unsigned char buff[TX_STACK_SIZE], *buff_p = buff;
29972765
size_t n, n2;
2998-
size_t is_elements = 0;
2999-
const bool is_bip143 = (flags & WALLY_TX_FLAG_USE_WITNESS) ? true : false;
30002766
int ret;
30012767
const struct tx_serialize_opts opts = {
30022768
sighash, tx_sighash, index, script, script_len, satoshi,
3003-
is_bip143, value, value_len
2769+
value, value_len
30042770
};
30052771

30062772
if (!is_valid_tx(tx) || BYTES_INVALID(script, script_len) ||
@@ -3009,23 +2775,13 @@ static int tx_get_signature_hash(const struct wally_tx *tx,
30092775
(flags & ~WALLY_TX_ALL_FLAGS) || !bytes_out || len < SHA256_LEN)
30102776
return WALLY_EINVAL;
30112777

3012-
if (extra || extra_len || extra_offset)
3013-
return WALLY_ERROR; /* FIXME: Not implemented yet */
3014-
30152778
if (index >= tx->num_inputs ||
30162779
(index >= tx->num_outputs && (sighash & WALLY_SIGHASH_MASK) == WALLY_SIGHASH_SINGLE)) {
3017-
if (!(flags & WALLY_TX_FLAG_USE_WITNESS)) {
3018-
memset(bytes_out, 0, SHA256_LEN);
3019-
bytes_out[0] = 0x1;
3020-
return WALLY_OK;
3021-
}
2780+
memset(bytes_out, 0, SHA256_LEN);
2781+
bytes_out[0] = 0x1;
2782+
return WALLY_OK;
30222783
}
30232784

3024-
#ifdef BUILD_ELEMENTS
3025-
if ((ret = wally_tx_is_elements(tx, &is_elements)) != WALLY_OK)
3026-
goto fail;
3027-
#endif
3028-
30292785
if ((ret = tx_get_length(tx, &opts, 0, &n, is_elements != 0)) != WALLY_OK)
30302786
goto fail;
30312787

@@ -3049,6 +2805,7 @@ static int tx_get_signature_hash(const struct wally_tx *tx,
30492805
wally_clear(buff, sizeof(buff));
30502806
return ret;
30512807
}
2808+
}
30522809

30532810
int wally_tx_get_signature_hash(const struct wally_tx *tx,
30542811
size_t index,

0 commit comments

Comments
 (0)