Skip to content

Commit fb634c4

Browse files
committed
Add P2TR detection in wally_scriptpubkey_get_type()
1 parent b4181f8 commit fb634c4

File tree

3 files changed

+37
-9
lines changed

3 files changed

+37
-9
lines changed

include/wally_script.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@ extern "C" {
1616
#define WALLY_SCRIPT_TYPE_P2WPKH 0x8
1717
#define WALLY_SCRIPT_TYPE_P2WSH 0x10
1818
#define WALLY_SCRIPT_TYPE_MULTISIG 0x20
19+
#define WALLY_SCRIPT_TYPE_P2TR 0x40
1920

2021
/* Standard script lengths */
2122
#define WALLY_SCRIPTPUBKEY_P2PKH_LEN 25 /** OP_DUP OP_HASH160 [HASH160] OP_EQUALVERIFY OP_CHECKSIG */
2223
#define WALLY_SCRIPTPUBKEY_P2SH_LEN 23 /** OP_HASH160 [HASH160] OP_EQUAL */
2324
#define WALLY_SCRIPTPUBKEY_P2WPKH_LEN 22 /** OP_0 [HASH160] */
2425
#define WALLY_SCRIPTPUBKEY_P2WSH_LEN 34 /** OP_0 [SHA256] */
26+
#define WALLY_SCRIPTPUBKEY_P2TR_LEN 34 /** OP_1 [X-ONLY-PUBKEY] */
2527

2628
#define WALLY_SCRIPTPUBKEY_OP_RETURN_MAX_LEN 83 /** OP_RETURN [80 bytes of data] */
2729

src/script.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -312,30 +312,38 @@ static bool scriptpubkey_is_p2pkh(const unsigned char *bytes, size_t bytes_len)
312312
{
313313
return bytes_len == WALLY_SCRIPTPUBKEY_P2PKH_LEN &&
314314
bytes[0] == OP_DUP && bytes[1] == OP_HASH160 &&
315-
bytes[2] == 20 && bytes[23] == OP_EQUALVERIFY &&
315+
bytes[2] == 20 && /* HASH160 */
316+
bytes[23] == OP_EQUALVERIFY &&
316317
bytes[24] == OP_CHECKSIG;
317318
}
318319

319320
static bool scriptpubkey_is_p2sh(const unsigned char *bytes, size_t bytes_len)
320321
{
321322
return bytes_len == WALLY_SCRIPTPUBKEY_P2SH_LEN &&
322323
bytes[0] == OP_HASH160 &&
323-
bytes[1] == 20 &&
324+
bytes[1] == 20 && /* HASH160 */
324325
bytes[22] == OP_EQUAL;
325326
}
326327

327328
static bool scriptpubkey_is_p2wpkh(const unsigned char *bytes, size_t bytes_len)
328329
{
329330
return bytes_len == WALLY_SCRIPTPUBKEY_P2WPKH_LEN &&
330-
bytes[0] == 0 &&
331-
bytes[1] == 20;
331+
bytes[0] == OP_0 && /* Segwit v0 */
332+
bytes[1] == 20; /* HASH160 */
332333
}
333334

334335
static bool scriptpubkey_is_p2wsh(const unsigned char *bytes, size_t bytes_len)
335336
{
336337
return bytes_len == WALLY_SCRIPTPUBKEY_P2WSH_LEN &&
337-
bytes[0] == 0 &&
338-
bytes[1] == 32;
338+
bytes[0] == OP_0 && /* Segwit v0 */
339+
bytes[1] == 32; /* SHA256 */
340+
}
341+
342+
static bool scriptpubkey_is_p2tr(const unsigned char *bytes, size_t bytes_len)
343+
{
344+
return bytes_len == WALLY_SCRIPTPUBKEY_P2TR_LEN &&
345+
bytes[0] == OP_1 && /* Segwit v1 */
346+
bytes[1] == 32; /* X-ONLY-PUBKEY */
339347
}
340348

341349
static bool scriptpubkey_is_multisig(const unsigned char *bytes, size_t bytes_len)
@@ -400,10 +408,13 @@ int wally_scriptpubkey_get_type(const unsigned char *bytes, size_t bytes_len,
400408
return WALLY_OK;
401409
}
402410
break;
403-
case WALLY_SCRIPTPUBKEY_P2WSH_LEN:
411+
case WALLY_SCRIPTPUBKEY_P2WSH_LEN: /* Also WALLY_SCRIPTPUBKEY_P2TR_LEN */
404412
if (scriptpubkey_is_p2wsh(bytes, bytes_len)) {
405413
*written = WALLY_SCRIPT_TYPE_P2WSH;
406414
return WALLY_OK;
415+
} else if (scriptpubkey_is_p2tr(bytes, bytes_len)) {
416+
*written = WALLY_SCRIPT_TYPE_P2TR;
417+
return WALLY_OK;
407418
}
408419
break;
409420
}

src/test/test_script.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
import unittest
22
from util import *
33

4+
SCRIPT_TYPE_UNKNOWN = 0x0
45
SCRIPT_TYPE_OP_RETURN = 0x1
56
SCRIPT_TYPE_P2PKH = 0x2
67
SCRIPT_TYPE_P2SH = 0x4
8+
SCRIPT_TYPE_P2WPKH = 0x8
9+
SCRIPT_TYPE_P2WSH = 0x10
710
SCRIPT_TYPE_MULTISIG = 0x20
11+
SCRIPT_TYPE_P2TR = 0x40
812

913
SCRIPT_MULTISIG_SORTED = 0x8
1014

@@ -45,9 +49,20 @@ def test_scriptpubkey_get_type(self):
4549
# Test invalid args, we test results with the functions that make scripts
4650
in_, in_len = make_cbuffer('00' * 16)
4751
for b, b_len in [(None, in_len), (in_, 0)]:
48-
ret, written = wally_scriptpubkey_get_type(b, b_len)
52+
ret, typ = wally_scriptpubkey_get_type(b, b_len)
4953
self.assertEqual(ret, WALLY_EINVAL)
50-
self.assertEqual(written, 0)
54+
self.assertEqual(typ, SCRIPT_TYPE_UNKNOWN)
55+
56+
# Segwit scripts
57+
segwit_cases = [
58+
[ '0014' + ('33' * 20), SCRIPT_TYPE_P2WPKH ],
59+
[ '0020' + ('33' * 32), SCRIPT_TYPE_P2WSH ],
60+
[ '5120' + ('33' * 32), SCRIPT_TYPE_P2TR ],
61+
]
62+
for script_hex, expected_type in segwit_cases:
63+
script, script_len = make_cbuffer(script_hex)
64+
ret, typ = wally_scriptpubkey_get_type(script, script_len)
65+
self.assertEqual((ret, typ), (WALLY_OK, expected_type))
5166

5267
def test_scriptpubkey_op_return_from_bytes(self):
5368
"""Tests for creating OP_RETURN scriptPubKeys"""

0 commit comments

Comments
 (0)