diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index ac216bc..b589d56 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index c608721..f937d01 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,10 +1,9 @@
-
-
+
\ No newline at end of file
diff --git a/proto/bb/deskriptor/v1alpha/deskriptor.proto b/proto/bb/deskriptor/v1alpha/deskriptor.proto
index 27913ef..a0938b2 100644
--- a/proto/bb/deskriptor/v1alpha/deskriptor.proto
+++ b/proto/bb/deskriptor/v1alpha/deskriptor.proto
@@ -46,6 +46,9 @@ enum ScriptType {
// Witness pay-to-pubkey-hash nested in P2SH. Corresponds to BIP 49
SCRIPT_TYPE_WPKH_NESTED = 3;
+
+ // Pay-to-taproot. Corresponds to BIP341.
+ SCRIPT_TYPE_P2TR = 4;
}
// This is included in the details section of an error returned from derivation.
diff --git a/src/main/kotlin/no/bb/deskriptor/service/Service.kt b/src/main/kotlin/no/bb/deskriptor/service/Service.kt
index 2c00e55..2063547 100644
--- a/src/main/kotlin/no/bb/deskriptor/service/Service.kt
+++ b/src/main/kotlin/no/bb/deskriptor/service/Service.kt
@@ -95,6 +95,7 @@ data class Script(private val script: ScriptType) {
// operators, and replace this `when` block with something that returns
// a list of operators. For another day.
ScriptType.SCRIPT_TYPE_WPKH_NESTED -> "sh(wpkh"
+ ScriptType.SCRIPT_TYPE_P2TR -> "tr"
ScriptType.SCRIPT_TYPE_UNSPECIFIED -> throw newStatus(Code.INVALID_ARGUMENT, "unspecified")
ScriptType.UNRECOGNIZED -> throw newStatus(Code.INVALID_ARGUMENT, "unrecognized script type: $script")
}
diff --git a/src/test/kotlin/no/bb/deskriptor/service/ServiceTest.kt b/src/test/kotlin/no/bb/deskriptor/service/ServiceTest.kt
index 4de340b..9abef3f 100644
--- a/src/test/kotlin/no/bb/deskriptor/service/ServiceTest.kt
+++ b/src/test/kotlin/no/bb/deskriptor/service/ServiceTest.kt
@@ -64,6 +64,72 @@ class ServiceTest : FunSpec({
) { it.assert() }
}
+ // https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki
+ context("bip86 test vectors") {
+ withData(
+ DeriveInput(
+ SCRIPT_TYPE_P2TR,
+ 0,
+ "xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ",
+ "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
+ ),
+ DeriveInput(
+ SCRIPT_TYPE_P2TR,
+ 1,
+ "xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ",
+ "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
+ ),
+ ) { it.assert() }
+ }
+
+ // stand sail fiction affair arch deer grow sight keen thing faculty virus
+ context("torkels sparrow wallet") {
+ withData(
+ DeriveInput(
+ SCRIPT_TYPE_P2TR,
+ 0,
+ "xpub6DDqmwVaNoavxHc8Agj4XuEVCC3RvuXHcQVcmVv59KivcBEoJG6brcQ49NCRtf25vA3YNPqeJwEa4TFCw1y5RGzULb72D3TQGV67xpEdH4j",
+ "bc1pcz7de4f64c4jm537f436cr7sq7wgfpfhdy4nf9avf9x9nac8fa5qwccp0z",
+ ),
+ DeriveInput(
+ SCRIPT_TYPE_P2TR,
+ 1,
+ "xpub6DDqmwVaNoavxHc8Agj4XuEVCC3RvuXHcQVcmVv59KivcBEoJG6brcQ49NCRtf25vA3YNPqeJwEa4TFCw1y5RGzULb72D3TQGV67xpEdH4j",
+ "bc1pzstq526x3xujh88jnmpvaq2tq8yk6dl2cu6a87qvzyslumxckwxq3yl7nf",
+ ),
+ DeriveInput(
+ SCRIPT_TYPE_P2TR,
+ 2,
+ "xpub6DDqmwVaNoavxHc8Agj4XuEVCC3RvuXHcQVcmVv59KivcBEoJG6brcQ49NCRtf25vA3YNPqeJwEa4TFCw1y5RGzULb72D3TQGV67xpEdH4j",
+ "bc1ph2r5c6c25520gqxsemvpt0pnue28jp2tlza2kdvmmtkqva30hs4qjp9nhj",
+ ),
+ ) { it.assert() }
+ }
+
+ context("bos sparrow wallet") {
+ withData(
+ DeriveInput(
+ SCRIPT_TYPE_P2TR,
+ 0,
+ "xpub6CPJGRoLhx72USPrYaGsiDZq6rBu6gzJruACdcyoRjffLGmecgW9rcojBmzQgw5Qsd8PN4KfSbiycVzDicvUW5m6RG9gVd41SjAVPcjWdq9",
+ "bc1pzzr5kkz5rtxw733tst7yxex8kgy2hanq0jchtt0xvp7cajqz9dkqj4pxev",
+ ),
+ DeriveInput(
+ SCRIPT_TYPE_P2TR,
+ 1,
+ "xpub6CPJGRoLhx72USPrYaGsiDZq6rBu6gzJruACdcyoRjffLGmecgW9rcojBmzQgw5Qsd8PN4KfSbiycVzDicvUW5m6RG9gVd41SjAVPcjWdq9",
+ "bc1psxyyfk9e4lykx7ghq4g44hunn75rmh3zvuxc5mud2tuae63yk3gqq2msra",
+ ),
+ DeriveInput(
+ SCRIPT_TYPE_P2TR,
+ 2,
+ "xpub6CPJGRoLhx72USPrYaGsiDZq6rBu6gzJruACdcyoRjffLGmecgW9rcojBmzQgw5Qsd8PN4KfSbiycVzDicvUW5m6RG9gVd41SjAVPcjWdq9",
+ "bc1pfmkr97h8dy50srk4p5c9c3fxg8m2uum4mrrfears2c7pt2ljx2xqu4ddwk",
+ ),
+ ) { it.assert() }
+ }
+
+
// generated with https://iancoleman.io/bip39/
context("iancoleman data") {