@@ -74,6 +74,13 @@ type InterpreterError interface {
7474
7575type Metadata = map [string ]Value
7676
77+ type Posting struct {
78+ Source string `json:"source"`
79+ Destination string `json:"destination"`
80+ Amount * big.Int `json:"amount"`
81+ Asset string `json:"asset"`
82+ }
83+
7784type ExecutionResult struct {
7885 Postings []Posting `json:"postings"`
7986
@@ -233,6 +240,7 @@ func RunProgram(
233240 CurrentBalanceQuery : BalanceQuery {},
234241 ctx : ctx ,
235242 FeatureFlags : featureFlags ,
243+ Postings : make ([]Posting , 0 ),
236244 }
237245
238246 st .varOriginPosition = true
@@ -257,13 +265,11 @@ func RunProgram(
257265 return nil , QueryBalanceError {WrappedError : genericErr }
258266 }
259267
260- st .Postings = make ([]Posting , 0 )
261268 for _ , statement := range program .Statements {
262- statementPostings , err := st .runStatement (statement )
269+ err := st .runStatement (statement )
263270 if err != nil {
264271 return nil , err
265272 }
266- st .Postings = append (st .Postings , statementPostings ... )
267273 }
268274
269275 res := & ExecutionResult {
@@ -287,7 +293,6 @@ type programState struct {
287293 ParsedVars map [string ]Value
288294 TxMeta map [string ]Value
289295 Senders []Sender
290- Receivers []Receiver
291296 Postings []Posting
292297
293298 // The funds allocated in the left side of a "through" source
@@ -318,35 +323,56 @@ func (st *programState) pushReceiver(name string, monetary *big.Int) {
318323 if monetary .Cmp (big .NewInt (0 )) == 0 {
319324 return
320325 }
321- st .Receivers = append (st .Receivers , Receiver {Name : name , Amount : monetary })
326+
327+ senders := st .fundsStack .Pull (monetary )
328+
329+ if name == KEPT_ADDR {
330+ return
331+ }
332+
333+ for _ , sender := range senders {
334+ postings := Posting {
335+ Source : sender .Name ,
336+ Destination : name ,
337+ Asset : st .CurrentAsset ,
338+ Amount : sender .Amount ,
339+ }
340+
341+ srcBalance := st .CachedBalances .fetchBalance (postings .Source , postings .Asset )
342+ srcBalance .Sub (srcBalance , postings .Amount )
343+
344+ destBalance := st .CachedBalances .fetchBalance (postings .Destination , postings .Asset )
345+ destBalance .Add (destBalance , postings .Amount )
346+
347+ st .Postings = append (st .Postings , postings )
348+ }
322349}
323350
324- func (st * programState ) runStatement (statement parser.Statement ) ([] Posting , InterpreterError ) {
351+ func (st * programState ) runStatement (statement parser.Statement ) InterpreterError {
325352 st .Senders = nil
326- st .Receivers = nil
327353
328354 switch statement := statement .(type ) {
329355 case * parser.FnCall :
330356 args , err := st .evaluateExpressions (statement .Args )
331357 if err != nil {
332- return nil , err
358+ return err
333359 }
334360
335361 switch statement .Caller .Name {
336362 case analysis .FnSetTxMeta :
337363 err := setTxMeta (st , statement .Caller .Range , args )
338364 if err != nil {
339- return nil , err
365+ return err
340366 }
341367 case analysis .FnSetAccountMeta :
342368 err := setAccountMeta (st , statement .Caller .Range , args )
343369 if err != nil {
344- return nil , err
370+ return err
345371 }
346372 default :
347- return nil , UnboundFunctionErr {Name : statement .Caller .Name }
373+ return UnboundFunctionErr {Name : statement .Caller .Name }
348374 }
349- return nil , nil
375+ return nil
350376
351377 case * parser.SendStatement :
352378 return st .runSendStatement (* statement )
@@ -356,32 +382,19 @@ func (st *programState) runStatement(statement parser.Statement) ([]Posting, Int
356382
357383 default :
358384 utils.NonExhaustiveMatchPanic [any ](statement )
359- return nil , nil
360- }
361- }
362-
363- func (st * programState ) getPostings () ([]Posting , InterpreterError ) {
364- postings := Reconcile (st .CurrentAsset , st .Senders , st .Receivers )
365-
366- for _ , posting := range postings {
367- srcBalance := st .CachedBalances .fetchBalance (posting .Source , posting .Asset )
368- srcBalance .Sub (srcBalance , posting .Amount )
369-
370- destBalance := st .CachedBalances .fetchBalance (posting .Destination , posting .Asset )
371- destBalance .Add (destBalance , posting .Amount )
385+ return nil
372386 }
373- return postings , nil
374387}
375388
376- func (st * programState ) runSaveStatement (saveStatement parser.SaveStatement ) ([] Posting , InterpreterError ) {
389+ func (st * programState ) runSaveStatement (saveStatement parser.SaveStatement ) InterpreterError {
377390 asset , amt , err := st .evaluateSentAmt (saveStatement .SentValue )
378391 if err != nil {
379- return nil , err
392+ return err
380393 }
381394
382395 account , err := evaluateExprAs (st , saveStatement .Amount , expectAccount )
383396 if err != nil {
384- return nil , err
397+ return err
385398 }
386399
387400 balance := st .CachedBalances .fetchBalance (* account , * asset )
@@ -391,7 +404,7 @@ func (st *programState) runSaveStatement(saveStatement parser.SaveStatement) ([]
391404 } else {
392405 // Do not allow negative saves
393406 if amt .Cmp (big .NewInt (0 )) == - 1 {
394- return nil , NegativeAmountErr {
407+ return NegativeAmountErr {
395408 Range : saveStatement .SentValue .GetRange (),
396409 Amount : MonetaryInt (* amt ),
397410 }
@@ -405,55 +418,55 @@ func (st *programState) runSaveStatement(saveStatement parser.SaveStatement) ([]
405418 }
406419 }
407420
408- return nil , nil
421+ return nil
409422}
410423
411- func (st * programState ) runSendStatement (statement parser.SendStatement ) ([] Posting , InterpreterError ) {
424+ func (st * programState ) runSendStatement (statement parser.SendStatement ) InterpreterError {
412425 switch sentValue := statement .SentValue .(type ) {
413426 case * parser.SentValueAll :
414427 asset , err := evaluateExprAs (st , sentValue .Asset , expectAsset )
415428 if err != nil {
416- return nil , err
429+ return err
417430 }
418431 st .CurrentAsset = * asset
432+ st .fundsStack = nil
419433 sentAmt , err := st .sendAll (statement .Source )
420434 if err != nil {
421- return nil , err
422- }
423- err = st .receiveFrom (statement .Destination , sentAmt )
424- if err != nil {
425- return nil , err
435+ return err
426436 }
427- return st .getPostings ()
437+ fs := newFundsStack (st .Senders )
438+ st .fundsStack = & fs
439+
440+ return st .receiveFrom (statement .Destination , sentAmt )
428441
429442 case * parser.SentValueLiteral :
430443 monetary , err := evaluateExprAs (st , sentValue .Monetary , expectMonetary )
431444 if err != nil {
432- return nil , err
445+ return err
433446 }
434447 st .CurrentAsset = string (monetary .Asset )
448+ st .fundsStack = nil
435449
436450 monetaryAmt := (* big .Int )(& monetary .Amount )
437451 if monetaryAmt .Cmp (big .NewInt (0 )) == - 1 {
438- return nil , NegativeAmountErr {Amount : monetary .Amount }
452+ return NegativeAmountErr {Amount : monetary .Amount }
439453 }
440454
441455 err = st .trySendingExact (statement .Source , monetaryAmt )
442456 if err != nil {
443- return nil , err
457+ return err
444458 }
445459
460+ fs := newFundsStack (st .Senders )
461+ st .fundsStack = & fs
462+
446463 // TODO simplify pointers
447464 amt := big .Int (monetary .Amount )
448- err = st .receiveFrom (statement .Destination , & amt )
449- if err != nil {
450- return nil , err
451- }
465+ return st .receiveFrom (statement .Destination , & amt )
452466
453- return st .getPostings ()
454467 default :
455468 utils.NonExhaustiveMatchPanic [any ](sentValue )
456- return nil , nil
469+ return nil
457470 }
458471
459472}
0 commit comments