Skip to content

Commit

Permalink
Support parsing multiple levels descriptors (ark-network#325)
Browse files Browse the repository at this point in the history
* [descriptor] fix parser to support multiple levels descriptors

* add andTokenSize constant
  • Loading branch information
louisinger authored Sep 20, 2024
1 parent 9e3d667 commit 877b7d3
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 12 deletions.
21 changes: 9 additions & 12 deletions common/descriptor/expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ var (
ErrNotExpectedPolicy = errors.New("not the expected policy")
)

const (
andTokenSize = len("and(")
)

type Expression interface {
Parse(policy string) error
Script(verify bool) (string, error)
Expand Down Expand Up @@ -156,28 +160,21 @@ func (e *And) Parse(policy string) error {
return ErrNotExpectedPolicy
}

index := strings.LastIndexByte(policy, ')')
if index == -1 {
return ErrInvalidAndPolicy
}

childrenPolicy := policy[4:index]
if len(childrenPolicy) == 0 {
parts, err := splitScriptTree(policy[andTokenSize : len(policy)-1])
if err != nil {
return ErrInvalidAndPolicy
}

children := strings.Split(childrenPolicy, ",")
if len(children) != 2 {
fmt.Println(children)
if len(parts) != 2 {
return ErrInvalidAndPolicy
}

first, err := parseExpression(children[0])
first, err := parseExpression(parts[0])
if err != nil {
return err
}

second, err := parseExpression(children[1])
second, err := parseExpression(parts[1])
if err != nil {
return err
}
Expand Down
5 changes: 5 additions & 0 deletions common/descriptor/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ const UnspendableKey = "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f281

func ParseTaprootDescriptor(desc string) (*TaprootDescriptor, error) {
desc = strings.ReplaceAll(desc, " ", "")
desc = strings.ReplaceAll(desc, "\n", "")
desc = strings.ReplaceAll(desc, "\t", "")
desc = strings.ReplaceAll(desc, "\r", "")

if !strings.HasPrefix(desc, "tr(") || !strings.HasSuffix(desc, ")") {
return nil, fmt.Errorf("invalid descriptor format")
Expand Down Expand Up @@ -93,6 +96,8 @@ func splitScriptTree(scriptTreeStr string) ([]string, error) {

for _, char := range scriptTreeStr {
switch char {
case '{', '}':
continue
case '(':
depth++
current.WriteRune(char)
Expand Down
155 changes: 155 additions & 0 deletions common/descriptor/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,161 @@ func TestParseTaprootDescriptor(t *testing.T) {
},
wantErr: false,
},
{
name: "Multiple level descriptor",
desc: `
tr(
0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,
{
{
{
and(and(pk(873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465), pk(873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465)), pk(873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465)),
and(older(512), and(pk(873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465), pk(873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465)))
},
{
and(and(pk(873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465), pk(873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465)), pk(873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465)),
and(older(1024), and(pk(873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465), pk(873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465)))
}
},
{
and(older(512), pk(873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465)),
and(older(512), and(pk(873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465), pk(873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465)))
}
}
)
`,
expected: descriptor.TaprootDescriptor{
InternalKey: descriptor.Key{Hex: "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0"},
ScriptTree: []descriptor.Expression{
&descriptor.And{
First: &descriptor.And{
First: &descriptor.PK{
Key: descriptor.XOnlyKey{
descriptor.Key{
Hex: "873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465",
},
},
},
Second: &descriptor.PK{
Key: descriptor.XOnlyKey{
descriptor.Key{
Hex: "873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465",
},
},
},
},
Second: &descriptor.PK{
Key: descriptor.XOnlyKey{
descriptor.Key{
Hex: "873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465",
},
},
},
},
&descriptor.And{
First: &descriptor.Older{
Timeout: 512,
},
Second: &descriptor.And{
First: &descriptor.PK{
Key: descriptor.XOnlyKey{
descriptor.Key{
Hex: "873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465",
},
},
},
Second: &descriptor.PK{
Key: descriptor.XOnlyKey{
descriptor.Key{
Hex: "873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465",
},
},
},
},
},
&descriptor.And{
First: &descriptor.And{
First: &descriptor.PK{
Key: descriptor.XOnlyKey{
descriptor.Key{
Hex: "873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465",
},
},
},
Second: &descriptor.PK{
Key: descriptor.XOnlyKey{
descriptor.Key{
Hex: "873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465",
},
},
},
},
Second: &descriptor.PK{
Key: descriptor.XOnlyKey{
descriptor.Key{
Hex: "873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465",
},
},
},
},
&descriptor.And{
First: &descriptor.Older{
Timeout: 1024,
},
Second: &descriptor.And{
First: &descriptor.PK{
Key: descriptor.XOnlyKey{
descriptor.Key{
Hex: "873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465",
},
},
},
Second: &descriptor.PK{
Key: descriptor.XOnlyKey{
descriptor.Key{
Hex: "873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465",
},
},
},
},
},
&descriptor.And{
First: &descriptor.Older{
Timeout: 512,
},
Second: &descriptor.PK{
Key: descriptor.XOnlyKey{
descriptor.Key{
Hex: "873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465",
},
},
},
},
&descriptor.And{
First: &descriptor.Older{
Timeout: 512,
},
Second: &descriptor.And{
First: &descriptor.PK{
Key: descriptor.XOnlyKey{
descriptor.Key{
Hex: "873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465",
},
},
},
Second: &descriptor.PK{
Key: descriptor.XOnlyKey{
descriptor.Key{
Hex: "873079a0091c9b16abd1f8c508320b07f0d50144d09ccd792ce9c915dac60465",
},
},
},
},
},
},
},
wantErr: false,
},
}

for _, tt := range tests {
Expand Down

0 comments on commit 877b7d3

Please sign in to comment.