Skip to content

Commit a5dd29b

Browse files
committed
Merge branch 'stop_using_parser_combinator' into miniscript_final_version_rust
2 parents beb91c4 + e99259b commit a5dd29b

File tree

5 files changed

+85
-83
lines changed

5 files changed

+85
-83
lines changed

NBitcoin.Tests/MiniscriptTests.cs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,22 @@ public void PolicyParserTest()
214214

215215
var strOr = $"or(99@pk({PubKeys[0]}),pk({PubKeys[1]}))";
216216
// var strOr = $"or(pk({PubKeys[0]}),pk({PubKeys[1]}))";
217-
var msRealOr = ConcretePolicy<PubKey, uint160>.Parse(strOr);
218-
Assert.True(msRealOr.IsValid());
217+
var orRes = ConcretePolicy<PubKey, uint160>.Parse(strOr);
218+
Assert.True(orRes.IsValid());
219+
220+
var strNestedOr = $"or(after(3),{strOr})";
221+
var nestedOrRes = ConcretePolicy<PubKey, uint160>.Parse(strNestedOr);
222+
Assert.True(nestedOrRes.IsValid());
223+
224+
var strAnd = $"and(older(3),{strNestedOr})";
225+
var andRes = ConcretePolicy<PubKey, uint160>.Parse(strAnd);
226+
Assert.True(andRes.IsValid());
227+
228+
var hash256 = Crypto.Hashes.Hash256(PubKeys[2].ToBytes()).ToString();
229+
var hash160 = Crypto.Hashes.Hash160(PubKeys[2].ToBytes()).ToString();
230+
var strThresh = $"thresh(2,hash256({hash256}),{strAnd},hash160({hash160}))";
231+
var threshRes = ConcretePolicy<PubKey,uint160>.Parse(strThresh);
232+
Assert.True(threshRes.IsValid());
219233
}
220234

221235
[Fact]
@@ -224,11 +238,14 @@ public void MiniscriptParserTest()
224238
{
225239
var pkStr = $"c:pk({PubKeys[0]})";
226240
var orStr = $"or_b(c:pk({PubKeys[0]}),sc:pk({PubKeys[1]}))";
227-
var andStr = $"and(time(3),{orStr})";
241+
// var andStr = $"";
228242
// var orMs = Miniscript<PubKey, uint160>.Parse(orStr);
229243
var pkRes = MiniscriptDSLParser<PubKey, uint160>.ParseTerminal(pkStr);
244+
Assert.True(pkRes is Terminal<PubKey, uint160>.Check c && (c.Item.Node is Terminal<PubKey, uint160>.Pk));
245+
230246
var orRes = MiniscriptDSLParser<PubKey, uint160>.ParseTerminal(orStr);
231-
var andRes = MiniscriptDSLParser<PubKey, uint160>.ParseTerminal(andStr);
247+
Assert.True(orRes is Terminal<PubKey, uint160>.OrB);
248+
// var andRes = MiniscriptDSLParser<PubKey, uint160>.ParseTerminal(andStr);
232249
}
233250
}
234251
}

NBitcoin/Scripting/Miniscript/AstElem.cs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,14 @@ public ThreshM(uint item1, TPk[] item2): base(Tags.ThreshM)
314314

315315
public static Terminal<TPk, TPKh> NewTrue() => Terminal<TPk, TPKh>.True;
316316
public static Terminal<TPk, TPKh> NewFalse() => Terminal<TPk, TPKh>.False;
317-
public static Terminal<TPk, TPKh> NewPk(TPk item) => new Pk(item);
317+
public static Terminal<TPk, TPKh> NewPk(TPk item)
318+
{
319+
if (item is null)
320+
throw new ArgumentNullException(nameof(item));
321+
322+
return new Pk(item);
323+
}
324+
318325
public static Terminal<TPk, TPKh> NewPkH(TPKh item) => new PkH(item);
319326
public static Terminal<TPk, TPKh> NewAfter(uint item) => new After(item);
320327
public static Terminal<TPk, TPKh> NewOlder(uint item) => new Older(item);
@@ -328,7 +335,14 @@ public static Terminal<TPk, TPKh> NewHash160(uint160 item)
328335
=> new Hash160(item);
329336
public static Terminal<TPk, TPKh> NewAlt(Miniscript<TPk, TPKh> item) => new Terminal<TPk, TPKh>.Alt(item);
330337
public static Terminal<TPk, TPKh> NewSwap(Miniscript<TPk, TPKh> item) => new Terminal<TPk, TPKh>.Swap(item);
331-
public static Terminal<TPk, TPKh> NewCheck(Miniscript<TPk, TPKh> item) => new Terminal<TPk, TPKh>.Check(item);
338+
public static Terminal<TPk, TPKh> NewCheck(Miniscript<TPk, TPKh> item)
339+
{
340+
if (item is null)
341+
throw new ArgumentNullException(nameof(item));
342+
343+
return new Check(item);
344+
}
345+
332346
public static Terminal<TPk, TPKh> NewDupIf(Miniscript<TPk, TPKh> item) => new DupIf(item);
333347
public static Terminal<TPk, TPKh> NewVerify(Miniscript<TPk, TPKh> item) => new Verify(item);
334348
public static Terminal<TPk, TPKh> NewNonZero(Miniscript<TPk, TPKh> item) => new NonZero(item);
@@ -344,7 +358,15 @@ public static Terminal<TPk, TPKh> NewAndOr(Miniscript<TPk, TPKh> item1, Miniscri
344358
=> new AndOr(item1, item2, item3);
345359

346360
public static Terminal<TPk, TPKh> NewOrB(Miniscript<TPk, TPKh> item1, Miniscript<TPk, TPKh> item2)
347-
=> new OrB(item1, item2);
361+
{
362+
if (item1 is null)
363+
throw new ArgumentNullException(nameof(item1));
364+
365+
if (item2 is null)
366+
throw new ArgumentNullException(nameof(item2));
367+
368+
return new OrB(item1, item2);
369+
}
348370

349371
public static Terminal<TPk, TPKh> NewOrD(Miniscript<TPk, TPKh> item1, Miniscript<TPk, TPKh> item2)
350372
=> new OrD(item1, item2);

NBitcoin/Scripting/Miniscript/MiniscriptDSLParser.Terminal.cs

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,20 @@ from t in ExprP("hash160").Then(s => TryConvert(s, uint160.Parse))
5353
private static Parser<char, Terminal<TPk, TPKh>> PWrapper(char identifier,
5454
Func<Miniscript<TPk, TPKh>, Terminal<TPk, TPKh>> construct)
5555
=>
56-
from _t in Parse.Char(identifier).Then(_ => Parse.Char(':'))
57-
from inner in Parse.Ref(() => TerminalDSLParser)
58-
.Except(PWrapper(identifier, construct)) // should not have the same wrapper twice
59-
select construct(Miniscript<TPk, TPKh>.FromAst(inner));
56+
(from _t in Parse.Char(identifier).Then(_ => Parse.Char(':'))
57+
from inner in Parse.Ref(PNonWrappers)
58+
select construct(Miniscript<TPk, TPKh>.FromAst(inner)))
59+
.Or(
60+
from _t in Parse.Char(identifier)
61+
from x in Parse.Ref(() => PWrappers).Except(PWrapper(identifier, construct))
62+
select x
63+
);
6064

6165
private static Parser<char, Terminal<TPk, TPKh>> PBinary(
6266
string identifier,
6367
Func<Miniscript<TPk, TPKh>, Miniscript<TPk, TPKh>, Terminal<TPk, TPKh>> constructor
6468
) =>
65-
from s in PSubExprs(identifier, () => TerminalDSLParser)
69+
from s in PSubExprs(identifier, TerminalDSLParser)
6670
where s.Count() == 2
6771
select constructor(Miniscript<TPk, TPKh>.FromAst(s.ElementAt(0)),
6872
Miniscript<TPk, TPKh>.FromAst(s.ElementAt(1)));
@@ -71,7 +75,7 @@ private static Parser<char, Terminal<TPk, TPKh>> PTernary(
7175
string identifier,
7276
Func<Miniscript<TPk, TPKh>, Miniscript<TPk, TPKh>, Miniscript<TPk, TPKh>, Terminal<TPk, TPKh>> constructor
7377
) =>
74-
from s in PSubExprs(identifier, () => TerminalDSLParser)
78+
from s in PSubExprs(identifier, TerminalDSLParser)
7579
where s.Count() == 3
7680
select constructor(
7781
Miniscript<TPk, TPKh>.FromAst(s.ElementAt(0)),
@@ -82,30 +86,31 @@ select constructor(
8286
PThresh(
8387
"thresh",
8488
Terminal<TPk, TPKh>.NewThresh,
85-
() => TerminalDSLParser.Select(t => Miniscript<TPk, TPKh>.FromAst(t)));
89+
() => TerminalDSLParser().Select(t => Miniscript<TPk, TPKh>.FromAst(t)));
8690

8791
private static Parser<char, Terminal<TPk, TPKh>> PTerminalThreshM =
8892
PThresh("thresh_m", Terminal<TPk, TPKh>.NewThreshM,
8993
() => (from pk in ExprP("pk").Then(s => TryParseMiniscriptKey(s))
9094
select pk));
9195

92-
private static readonly Parser<char, Terminal<TPk, TPKh>> TerminalDSLParser =
93-
// ------ leafs ------
94-
Parse.Ref(() => PTerminalPk)
95-
.Or(Parse.Ref(() => PTerminalPkH))
96-
.Or(Parse.Ref(() => PTerminalAfter))
97-
.Or(Parse.Ref(() => PTerminalOlder))
98-
.Or(Parse.Ref(() => PTerminalSha256))
99-
.Or(Parse.Ref(() => PTerminalHash256))
100-
.Or(Parse.Ref(() => PTerminalRipemd160))
101-
.Or(Parse.Ref(() => PTerminalHash160))
102-
// ------- wrappers --------
103-
.Or(PWrapper('a', Terminal<TPk, TPKh>.NewAlt))
104-
.Or(PWrapper('s', Terminal<TPk, TPKh>.NewSwap))
96+
private static readonly Parser<char, Terminal<TPk, TPKh>> PWrappers =
97+
PWrapper('a', Terminal<TPk, TPKh>.NewAlt)
10598
.Or(PWrapper('c', Terminal<TPk, TPKh>.NewCheck))
99+
.Or(PWrapper('s', Terminal<TPk, TPKh>.NewSwap))
106100
.Or(PWrapper('d', Terminal<TPk, TPKh>.NewDupIf))
107101
.Or(PWrapper('v', Terminal<TPk, TPKh>.NewVerify))
108-
.Or(PWrapper('j', Terminal<TPk, TPKh>.NewZeroNotEqual))
102+
.Or(PWrapper('j', Terminal<TPk, TPKh>.NewZeroNotEqual));
103+
104+
private static Parser<char, Terminal<TPk, TPKh>> PNonWrappers() =>
105+
// ------ leafs ------
106+
PTerminalPk
107+
.Or(PTerminalPkH)
108+
.Or(PTerminalAfter)
109+
.Or(PTerminalOlder)
110+
.Or(PTerminalSha256)
111+
.Or(PTerminalHash256)
112+
.Or(PTerminalRipemd160)
113+
.Or(PTerminalHash160)
109114
// ------- Conjunctions -----
110115
.Or(PBinary("and_v", Terminal<TPk, TPKh>.NewAndV))
111116
.Or(PBinary("and_b", Terminal<TPk, TPKh>.NewAndB))
@@ -118,8 +123,12 @@ select constructor(
118123
// ------- Thresholds ------
119124
.Or(Parse.Ref(() => PTerminalThresh))
120125
.Or(Parse.Ref(() => PTerminalThreshM));
126+
private static Parser<char, Terminal<TPk, TPKh>> TerminalDSLParser() =>
127+
Parse.Ref(() => PWrappers)
128+
.Or(PNonWrappers());
129+
// ------- wrappers --------
121130

122131
public static Terminal<TPk, TPKh> ParseTerminal(string input)
123-
=> Parse.Ref(() => TerminalDSLParser).Parse(input);
132+
=> TerminalDSLParser().Parse(input);
124133
}
125134
}

NBitcoin/Scripting/Miniscript/MiniscriptDSLParsers.ConcretePolicy.cs

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -20,52 +20,6 @@ from x in Parse.CharExcept(')').Many().Text()
2020
from rightB in Parse.Char(')').Token()
2121
select x;
2222

23-
private static string[] SafeSplit(string s)
24-
{
25-
var parenthCount = 0;
26-
var items = new List<string>();
27-
var charSoFar = new List<char>();
28-
var length = s.Length;
29-
for (int i = 0; i < length; i++)
30-
{
31-
var c = s[i];
32-
if (c == '(')
33-
{
34-
parenthCount++;
35-
charSoFar.Add(c);
36-
}
37-
else if (c == ')')
38-
{
39-
parenthCount--;
40-
charSoFar.Add(c);
41-
}
42-
else if (parenthCount != 0)
43-
{
44-
charSoFar.Add(c);
45-
}
46-
47-
if (parenthCount == 0)
48-
{
49-
if (i == length - 1)
50-
{
51-
charSoFar.Add(c);
52-
}
53-
if (c == ',' || i == length - 1)
54-
{
55-
var charsCopy = new List<char>(charSoFar);
56-
charSoFar = new List<char>();
57-
var item = new String(charsCopy.ToArray()).Trim();
58-
items.Add(item);
59-
}
60-
else
61-
{
62-
charSoFar.Add(c);
63-
}
64-
}
65-
}
66-
return items.ToArray();
67-
}
68-
6923
internal static Parser<char, T> TryConvert<T>(string str, Func<string, T> converter)
7024
{
7125
return i =>

NBitcoin/Scripting/Miniscript/Types/Property.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,17 @@ internal static T TypeCheck(Terminal<TPk, TPKh> fragment)
2626

2727
private static T TypeCheckCore(Terminal<TPk, TPKh> fragment,Func<int, T> child)
2828
{
29+
if (fragment is null)
30+
throw new ArgumentNullException(nameof(fragment));
31+
2932
T GetChild(Terminal<TPk, TPKh> sub, int n)
3033
{
31-
try
32-
{
33-
return child(n);
34-
}
35-
catch
36-
{
37-
return TypeCheck(sub, _ => null);
38-
}
34+
var r = child(n);
35+
if (r is null)
36+
return TypeCheck(sub, _ => null);
37+
return r;
3938
}
39+
4040
switch (fragment.Tag)
4141
{
4242
case Terminal<TPk, TPKh>.Tags.True:

0 commit comments

Comments
 (0)