mirror of
https://github.com/aljazceru/ark.git
synced 2025-12-17 12:14:21 +01:00
Support parsing multiple levels descriptors (#325)
* [descriptor] fix parser to support multiple levels descriptors * add andTokenSize constant
This commit is contained in:
@@ -19,6 +19,10 @@ var (
|
|||||||
ErrNotExpectedPolicy = errors.New("not the expected policy")
|
ErrNotExpectedPolicy = errors.New("not the expected policy")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
andTokenSize = len("and(")
|
||||||
|
)
|
||||||
|
|
||||||
type Expression interface {
|
type Expression interface {
|
||||||
Parse(policy string) error
|
Parse(policy string) error
|
||||||
Script(verify bool) (string, error)
|
Script(verify bool) (string, error)
|
||||||
@@ -156,28 +160,21 @@ func (e *And) Parse(policy string) error {
|
|||||||
return ErrNotExpectedPolicy
|
return ErrNotExpectedPolicy
|
||||||
}
|
}
|
||||||
|
|
||||||
index := strings.LastIndexByte(policy, ')')
|
parts, err := splitScriptTree(policy[andTokenSize : len(policy)-1])
|
||||||
if index == -1 {
|
if err != nil {
|
||||||
return ErrInvalidAndPolicy
|
return ErrInvalidAndPolicy
|
||||||
}
|
}
|
||||||
|
|
||||||
childrenPolicy := policy[4:index]
|
if len(parts) != 2 {
|
||||||
if len(childrenPolicy) == 0 {
|
|
||||||
return ErrInvalidAndPolicy
|
return ErrInvalidAndPolicy
|
||||||
}
|
}
|
||||||
|
|
||||||
children := strings.Split(childrenPolicy, ",")
|
first, err := parseExpression(parts[0])
|
||||||
if len(children) != 2 {
|
|
||||||
fmt.Println(children)
|
|
||||||
return ErrInvalidAndPolicy
|
|
||||||
}
|
|
||||||
|
|
||||||
first, err := parseExpression(children[0])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
second, err := parseExpression(children[1])
|
second, err := parseExpression(parts[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ const UnspendableKey = "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f281
|
|||||||
|
|
||||||
func ParseTaprootDescriptor(desc string) (*TaprootDescriptor, error) {
|
func ParseTaprootDescriptor(desc string) (*TaprootDescriptor, error) {
|
||||||
desc = strings.ReplaceAll(desc, " ", "")
|
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, ")") {
|
if !strings.HasPrefix(desc, "tr(") || !strings.HasSuffix(desc, ")") {
|
||||||
return nil, fmt.Errorf("invalid descriptor format")
|
return nil, fmt.Errorf("invalid descriptor format")
|
||||||
@@ -93,6 +96,8 @@ func splitScriptTree(scriptTreeStr string) ([]string, error) {
|
|||||||
|
|
||||||
for _, char := range scriptTreeStr {
|
for _, char := range scriptTreeStr {
|
||||||
switch char {
|
switch char {
|
||||||
|
case '{', '}':
|
||||||
|
continue
|
||||||
case '(':
|
case '(':
|
||||||
depth++
|
depth++
|
||||||
current.WriteRune(char)
|
current.WriteRune(char)
|
||||||
|
|||||||
@@ -179,6 +179,161 @@ func TestParseTaprootDescriptor(t *testing.T) {
|
|||||||
},
|
},
|
||||||
wantErr: false,
|
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 {
|
for _, tt := range tests {
|
||||||
|
|||||||
Reference in New Issue
Block a user