Description
compile doesn't check that keys in the policy are actual keys. It succeeds and returns a descriptor that fails only later, when someone tries to use it:
$ bdk-cli compile "pk(ABC)"
{
"descriptor": "wsh(pk(ABC))#8gmtcnaw"
}
$ bitcoin-cli deriveaddresses "wsh(pk(ABC))#8gmtcnaw"
error code: -5
error message:
pk(): key 'ABC' is not valid
The policy is parsed as Concrete<String>, and a String key accepts anything.
Came up before in #225 and in the #317 review.
Proposed fix
Parse as Concrete<DescriptorPublicKey> by default. Keys are validated at parse time, so placeholders are rejected while real keys and xpubs keep working. Hashes are typed too, so sha256(H) is rejected the same way.
Keep the current behavior behind a flag, e.g. --allow-placeholders, since pk(A) style policies are handy to see what a policy compiles to, and in tests where only the policy shape matters, not the keys. This breaks existing calls with placeholders, docs and tests would need the flag or real keys.
# placeholder key is rejected
$ bdk-cli compile "pk(ABC)"
Error: Generic error: Invalid policy: unexpected «Key too short (<66 char), doesn't match any format»
# placeholder hash is rejected
$ bdk-cli compile "and(pk(02e5b88fdb71c696e1a473f309a47535b7190e21a22bd25e7fc8bd055db3bba12f),sha256(H))"
Error: Generic error: Invalid policy: unexpected «failed to parse hex»
# real keys and xpubs compile
$ bdk-cli compile "or(pk(02e5b88fdb71c696e1a473f309a47535b7190e21a22bd25e7fc8bd055db3bba12f),pk(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/0/*))"
{
"descriptor": "wsh(or_b(pk(02e5b88fdb71c696e1a473f309a47535b7190e21a22bd25e7fc8bd055db3bba12f),s:pk(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/0/*)))#t459ja6u"
}
# placeholders still work with the flag
$ bdk-cli compile "pk(ABC)" --allow-placeholders
{
"descriptor": "wsh(pk(ABC))#8gmtcnaw"
}
See
Description
compiledoesn't check that keys in the policy are actual keys. It succeeds and returns a descriptor that fails only later, when someone tries to use it:The policy is parsed as
Concrete<String>, and aStringkey accepts anything.Came up before in #225 and in the #317 review.
Proposed fix
Parse as
Concrete<DescriptorPublicKey>by default. Keys are validated at parse time, so placeholders are rejected while real keys and xpubs keep working. Hashes are typed too, sosha256(H)is rejected the same way.Keep the current behavior behind a flag, e.g.
--allow-placeholders, sincepk(A)style policies are handy to see what a policy compiles to, and in tests where only the policy shape matters, not the keys. This breaks existing calls with placeholders, docs and tests would need the flag or real keys.See