Skip to content

Commit 317bea4

Browse files
committed
liquidity/script: add Starlark script evaluation package
Add a new package for evaluating Starlark scripts in the autoloop context. This includes: - context.go: Types exposed to scripts (ChannelInfo, PeerInfo, SwapRestrictions, BudgetInfo, InFlightInfo, AutoloopContext, SwapDecision) with Starlark Value interface implementations - builtins.go: Helper functions loop_out() and loop_in() for creating swap decisions in scripts - starlark.go: Evaluator for executing scripts with context data - starlark_test.go: Unit tests for script evaluation Starlark provides Python-like syntax with variables, functions, list comprehensions, and sorting - making complex swap logic readable and maintainable compared to expression languages.
1 parent d92eba4 commit 317bea4

4 files changed

Lines changed: 1428 additions & 0 deletions

File tree

liquidity/script/builtins.go

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package script
2+
3+
import (
4+
"fmt"
5+
6+
"go.starlark.net/starlark"
7+
)
8+
9+
// loopOutBuiltin creates a loop out swap decision.
10+
// Usage: loop_out(amount, channel_ids) or loop_out(amount, channel_ids, priority)
11+
func loopOutBuiltin(thread *starlark.Thread, fn *starlark.Builtin,
12+
args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
13+
14+
var amount starlark.Int
15+
var channelIDs *starlark.List
16+
var priority starlark.Int = starlark.MakeInt(1)
17+
18+
if err := starlark.UnpackArgs(fn.Name(), args, kwargs,
19+
"amount", &amount,
20+
"channel_ids", &channelIDs,
21+
"priority?", &priority,
22+
); err != nil {
23+
return nil, err
24+
}
25+
26+
// Validate amount.
27+
amtVal, ok := amount.Int64()
28+
if !ok {
29+
return nil, fmt.Errorf("amount overflow")
30+
}
31+
if amtVal <= 0 {
32+
return nil, fmt.Errorf("amount must be positive")
33+
}
34+
35+
// Convert channel IDs.
36+
ids := make([]starlark.Value, channelIDs.Len())
37+
for i := 0; i < channelIDs.Len(); i++ {
38+
ids[i] = channelIDs.Index(i)
39+
}
40+
41+
priorityVal, ok := priority.Int64()
42+
if !ok {
43+
return nil, fmt.Errorf("priority overflow")
44+
}
45+
46+
// Create the decision dict.
47+
dict := starlark.NewDict(4)
48+
if err := dict.SetKey(starlark.String("type"),
49+
starlark.String(SwapTypeLoopOut)); err != nil {
50+
return nil, err
51+
}
52+
if err := dict.SetKey(starlark.String("amount"), amount); err != nil {
53+
return nil, err
54+
}
55+
if err := dict.SetKey(starlark.String("channel_ids"),
56+
starlark.NewList(ids)); err != nil {
57+
return nil, err
58+
}
59+
if err := dict.SetKey(starlark.String("priority"),
60+
starlark.MakeInt64(priorityVal)); err != nil {
61+
return nil, err
62+
}
63+
64+
return dict, nil
65+
}
66+
67+
// loopInBuiltin creates a loop in swap decision.
68+
// Usage: loop_in(amount, peer_pubkey) or loop_in(amount, peer_pubkey, priority)
69+
func loopInBuiltin(thread *starlark.Thread, fn *starlark.Builtin,
70+
args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
71+
72+
var amount starlark.Int
73+
var peerPubkey starlark.String
74+
var priority starlark.Int = starlark.MakeInt(1)
75+
76+
if err := starlark.UnpackArgs(fn.Name(), args, kwargs,
77+
"amount", &amount,
78+
"peer_pubkey", &peerPubkey,
79+
"priority?", &priority,
80+
); err != nil {
81+
return nil, err
82+
}
83+
84+
// Validate amount.
85+
amtVal, ok := amount.Int64()
86+
if !ok {
87+
return nil, fmt.Errorf("amount overflow")
88+
}
89+
if amtVal <= 0 {
90+
return nil, fmt.Errorf("amount must be positive")
91+
}
92+
93+
// Validate peer pubkey.
94+
if len(peerPubkey) == 0 {
95+
return nil, fmt.Errorf("peer_pubkey cannot be empty")
96+
}
97+
98+
priorityVal, ok := priority.Int64()
99+
if !ok {
100+
return nil, fmt.Errorf("priority overflow")
101+
}
102+
103+
// Create the decision dict.
104+
dict := starlark.NewDict(4)
105+
if err := dict.SetKey(starlark.String("type"),
106+
starlark.String(SwapTypeLoopIn)); err != nil {
107+
return nil, err
108+
}
109+
if err := dict.SetKey(starlark.String("amount"), amount); err != nil {
110+
return nil, err
111+
}
112+
if err := dict.SetKey(starlark.String("peer_pubkey"), peerPubkey); err != nil {
113+
return nil, err
114+
}
115+
if err := dict.SetKey(starlark.String("priority"),
116+
starlark.MakeInt64(priorityVal)); err != nil {
117+
return nil, err
118+
}
119+
120+
return dict, nil
121+
}

0 commit comments

Comments
 (0)