Skip to content

Commit

Permalink
tokenvm integration passes using multiple result.Outputs
Browse files Browse the repository at this point in the history
  • Loading branch information
wlawt committed Apr 28, 2024
1 parent 6c617ef commit bd97396
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 89 deletions.
4 changes: 3 additions & 1 deletion chain/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ func (t *Transaction) Execute(
resultOutputs := [][][]byte{}
totalUsed := fees.Dimensions{}
var totalFeeRequired uint64
txSuccess := true
for i, action := range t.Actions {
actionID := action.GetActionID(uint8(i), t.id)
success, actionCUs, outputs, err := action.Execute(ctx, r, ts, timestamp, t.Auth.Actor(), actionID)
Expand All @@ -337,6 +338,7 @@ func (t *Transaction) Execute(
}
resultOutputs = append(resultOutputs, outputs)
if !success {
txSuccess = false
ts.Rollback(ctx, actionStart)
}

Expand Down Expand Up @@ -427,7 +429,7 @@ func (t *Transaction) Execute(
}
}
return &Result{
Success: true,
Success: txSuccess,
Outputs: resultOutputs,

Consumed: totalUsed,
Expand Down
16 changes: 8 additions & 8 deletions examples/tokenvm/actions/burn_asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,28 +53,28 @@ func (b *BurnAsset) Execute(
_ int64,
actor codec.Address,
_ codec.LID,
) (bool, uint64, []byte, error) {
) (bool, uint64, [][]byte, error) {
if b.Value == 0 {
return false, BurnComputeUnits, OutputValueZero, nil
return false, BurnComputeUnits, [][]byte{OutputValueZero}, nil
}
if err := storage.SubBalance(ctx, mu, actor, b.Asset, b.Value); err != nil {
return false, BurnComputeUnits, utils.ErrBytes(err), nil
return false, BurnComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
exists, symbol, decimals, metadata, supply, owner, err := storage.GetAsset(ctx, mu, b.Asset)
if err != nil {
return false, BurnComputeUnits, utils.ErrBytes(err), nil
return false, BurnComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
if !exists {
return false, BurnComputeUnits, OutputAssetMissing, nil
return false, BurnComputeUnits, [][]byte{OutputAssetMissing}, nil
}
newSupply, err := smath.Sub(supply, b.Value)
if err != nil {
return false, BurnComputeUnits, utils.ErrBytes(err), nil
return false, BurnComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
if err := storage.SetAsset(ctx, mu, b.Asset, symbol, decimals, metadata, newSupply, owner); err != nil {
return false, BurnComputeUnits, utils.ErrBytes(err), nil
return false, BurnComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
return true, BurnComputeUnits, nil, nil
return true, BurnComputeUnits, [][]byte{{}}, nil
}

func (*BurnAsset) MaxComputeUnits(chain.Rules) uint64 {
Expand Down
16 changes: 8 additions & 8 deletions examples/tokenvm/actions/close_order.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,27 +52,27 @@ func (c *CloseOrder) Execute(
_ int64,
actor codec.Address,
_ codec.LID,
) (bool, uint64, []byte, error) {
) (bool, uint64, [][]byte, error) {
exists, _, _, out, _, remaining, owner, err := storage.GetOrder(ctx, mu, c.Order)
if err != nil {
return false, CloseOrderComputeUnits, utils.ErrBytes(err), nil
return false, CloseOrderComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
if !exists {
return false, CloseOrderComputeUnits, OutputOrderMissing, nil
return false, CloseOrderComputeUnits, [][]byte{OutputOrderMissing}, nil
}
if owner != actor {
return false, CloseOrderComputeUnits, OutputUnauthorized, nil
return false, CloseOrderComputeUnits, [][]byte{OutputUnauthorized}, nil
}
if out != c.Out {
return false, CloseOrderComputeUnits, OutputWrongOut, nil
return false, CloseOrderComputeUnits, [][]byte{OutputWrongOut}, nil
}
if err := storage.DeleteOrder(ctx, mu, c.Order); err != nil {
return false, CloseOrderComputeUnits, utils.ErrBytes(err), nil
return false, CloseOrderComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
if err := storage.AddBalance(ctx, mu, actor, c.Out, remaining, true); err != nil {
return false, CloseOrderComputeUnits, utils.ErrBytes(err), nil
return false, CloseOrderComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
return true, CloseOrderComputeUnits, nil, nil
return true, CloseOrderComputeUnits, [][]byte{{}}, nil
}

func (*CloseOrder) MaxComputeUnits(chain.Rules) uint64 {
Expand Down
16 changes: 8 additions & 8 deletions examples/tokenvm/actions/create_asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,28 +48,28 @@ func (c *CreateAsset) Execute(
_ int64,
actor codec.Address,
actionID codec.LID,
) (bool, uint64, []byte, error) {
) (bool, uint64, [][]byte, error) {
if len(c.Symbol) == 0 {
return false, CreateAssetComputeUnits, OutputSymbolEmpty, nil
return false, CreateAssetComputeUnits, [][]byte{OutputSymbolEmpty}, nil
}
if len(c.Symbol) > MaxSymbolSize {
return false, CreateAssetComputeUnits, OutputSymbolTooLarge, nil
return false, CreateAssetComputeUnits, [][]byte{OutputSymbolTooLarge}, nil
}
if c.Decimals > MaxDecimals {
return false, CreateAssetComputeUnits, OutputDecimalsTooLarge, nil
return false, CreateAssetComputeUnits, [][]byte{OutputDecimalsTooLarge}, nil
}
if len(c.Metadata) == 0 {
return false, CreateAssetComputeUnits, OutputMetadataEmpty, nil
return false, CreateAssetComputeUnits, [][]byte{OutputMetadataEmpty}, nil
}
if len(c.Metadata) > MaxMetadataSize {
return false, CreateAssetComputeUnits, OutputMetadataTooLarge, nil
return false, CreateAssetComputeUnits, [][]byte{OutputMetadataTooLarge}, nil
}
// It should only be possible to overwrite an existing asset if there is
// a hash collision.
if err := storage.SetAsset(ctx, mu, actionID, c.Symbol, c.Decimals, c.Metadata, 0, actor); err != nil {
return false, CreateAssetComputeUnits, utils.ErrBytes(err), nil
return false, CreateAssetComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
return true, CreateAssetComputeUnits, nil, nil
return true, CreateAssetComputeUnits, [][]byte{{}}, nil
}

func (*CreateAsset) MaxComputeUnits(chain.Rules) uint64 {
Expand Down
18 changes: 9 additions & 9 deletions examples/tokenvm/actions/create_order.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,29 +73,29 @@ func (c *CreateOrder) Execute(
_ int64,
actor codec.Address,
actionID codec.LID,
) (bool, uint64, []byte, error) {
) (bool, uint64, [][]byte, error) {
if c.In == c.Out {
return false, CreateOrderComputeUnits, OutputSameInOut, nil
return false, CreateOrderComputeUnits, [][]byte{OutputSameInOut}, nil
}
if c.InTick == 0 {
return false, CreateOrderComputeUnits, OutputInTickZero, nil
return false, CreateOrderComputeUnits, [][]byte{OutputInTickZero}, nil
}
if c.OutTick == 0 {
return false, CreateOrderComputeUnits, OutputOutTickZero, nil
return false, CreateOrderComputeUnits, [][]byte{OutputOutTickZero}, nil
}
if c.Supply == 0 {
return false, CreateOrderComputeUnits, OutputSupplyZero, nil
return false, CreateOrderComputeUnits, [][]byte{OutputSupplyZero}, nil
}
if c.Supply%c.OutTick != 0 {
return false, CreateOrderComputeUnits, OutputSupplyMisaligned, nil
return false, CreateOrderComputeUnits, [][]byte{OutputSupplyMisaligned}, nil
}
if err := storage.SubBalance(ctx, mu, actor, c.Out, c.Supply); err != nil {
return false, CreateOrderComputeUnits, utils.ErrBytes(err), nil
return false, CreateOrderComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
if err := storage.SetOrder(ctx, mu, actionID, c.In, c.InTick, c.Out, c.OutTick, c.Supply, actor); err != nil {
return false, CreateOrderComputeUnits, utils.ErrBytes(err), nil
return false, CreateOrderComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
return true, CreateOrderComputeUnits, nil, nil
return true, CreateOrderComputeUnits, [][]byte{{}}, nil
}

func (*CreateOrder) MaxComputeUnits(chain.Rules) uint64 {
Expand Down
36 changes: 18 additions & 18 deletions examples/tokenvm/actions/fill_order.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,39 +67,39 @@ func (f *FillOrder) Execute(
_ int64,
actor codec.Address,
_ codec.LID,
) (bool, uint64, []byte, error) {
) (bool, uint64, [][]byte, error) {
exists, in, inTick, out, outTick, remaining, owner, err := storage.GetOrder(ctx, mu, f.Order)
if err != nil {
return false, NoFillOrderComputeUnits, utils.ErrBytes(err), nil
return false, NoFillOrderComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
if !exists {
return false, NoFillOrderComputeUnits, OutputOrderMissing, nil
return false, NoFillOrderComputeUnits, [][]byte{OutputOrderMissing}, nil
}
if owner != f.Owner {
return false, NoFillOrderComputeUnits, OutputWrongOwner, nil
return false, NoFillOrderComputeUnits, [][]byte{OutputWrongOwner}, nil
}
if in != f.In {
return false, NoFillOrderComputeUnits, OutputWrongIn, nil
return false, NoFillOrderComputeUnits, [][]byte{OutputWrongIn}, nil
}
if out != f.Out {
return false, NoFillOrderComputeUnits, OutputWrongOut, nil
return false, NoFillOrderComputeUnits, [][]byte{OutputWrongOut}, nil
}
if f.Value == 0 {
// This should be guarded via [Unmarshal] but we check anyways.
return false, NoFillOrderComputeUnits, OutputValueZero, nil
return false, NoFillOrderComputeUnits, [][]byte{OutputValueZero}, nil
}
if f.Value%inTick != 0 {
return false, NoFillOrderComputeUnits, OutputValueMisaligned, nil
return false, NoFillOrderComputeUnits, [][]byte{OutputValueMisaligned}, nil
}
// Determine amount of [Out] counterparty will receive if the trade is
// successful.
outputAmount, err := smath.Mul64(outTick, f.Value/inTick)
if err != nil {
return false, NoFillOrderComputeUnits, utils.ErrBytes(err), nil
return false, NoFillOrderComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
if outputAmount == 0 {
// This should never happen because [f.Value] > 0
return false, NoFillOrderComputeUnits, OutputInsufficientOutput, nil
return false, NoFillOrderComputeUnits, [][]byte{OutputInsufficientOutput}, nil
}
var (
inputAmount = f.Value
Expand All @@ -125,32 +125,32 @@ func (f *FillOrder) Execute(
}
if inputAmount == 0 {
// Don't allow free trades (can happen due to refund rounding)
return false, NoFillOrderComputeUnits, OutputInsufficientInput, nil
return false, NoFillOrderComputeUnits, [][]byte{OutputInsufficientInput}, nil
}
if err := storage.SubBalance(ctx, mu, actor, f.In, inputAmount); err != nil {
return false, NoFillOrderComputeUnits, utils.ErrBytes(err), nil
return false, NoFillOrderComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
if err := storage.AddBalance(ctx, mu, f.Owner, f.In, inputAmount, true); err != nil {
return false, NoFillOrderComputeUnits, utils.ErrBytes(err), nil
return false, NoFillOrderComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
if err := storage.AddBalance(ctx, mu, actor, f.Out, outputAmount, true); err != nil {
return false, NoFillOrderComputeUnits, utils.ErrBytes(err), nil
return false, NoFillOrderComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
if shouldDelete {
if err := storage.DeleteOrder(ctx, mu, f.Order); err != nil {
return false, NoFillOrderComputeUnits, utils.ErrBytes(err), nil
return false, NoFillOrderComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
} else {
if err := storage.SetOrder(ctx, mu, f.Order, in, inTick, out, outTick, orderRemaining, owner); err != nil {
return false, NoFillOrderComputeUnits, utils.ErrBytes(err), nil
return false, NoFillOrderComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
}
or := &OrderResult{In: inputAmount, Out: outputAmount, Remaining: orderRemaining}
output, err := or.Marshal()
if err != nil {
return false, NoFillOrderComputeUnits, utils.ErrBytes(err), nil
return false, NoFillOrderComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
return true, FillOrderComputeUnits, output, nil
return true, FillOrderComputeUnits, [][]byte{output}, nil
}

func (*FillOrder) MaxComputeUnits(chain.Rules) uint64 {
Expand Down
20 changes: 10 additions & 10 deletions examples/tokenvm/actions/mint_asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,34 +56,34 @@ func (m *MintAsset) Execute(
_ int64,
actor codec.Address,
_ codec.LID,
) (bool, uint64, []byte, error) {
) (bool, uint64, [][]byte, error) {
if m.Asset == codec.EmptyAddress {
return false, MintAssetComputeUnits, OutputAssetIsNative, nil
return false, MintAssetComputeUnits, [][]byte{OutputAssetIsNative}, nil
}
if m.Value == 0 {
return false, MintAssetComputeUnits, OutputValueZero, nil
return false, MintAssetComputeUnits, [][]byte{OutputValueZero}, nil
}
exists, symbol, decimals, metadata, supply, owner, err := storage.GetAsset(ctx, mu, m.Asset)
if err != nil {
return false, MintAssetComputeUnits, utils.ErrBytes(err), nil
return false, MintAssetComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
if !exists {
return false, MintAssetComputeUnits, OutputAssetMissing, nil
return false, MintAssetComputeUnits, [][]byte{OutputAssetMissing}, nil
}
if owner != actor {
return false, MintAssetComputeUnits, OutputWrongOwner, nil
return false, MintAssetComputeUnits, [][]byte{OutputWrongOwner}, nil
}
newSupply, err := smath.Add64(supply, m.Value)
if err != nil {
return false, MintAssetComputeUnits, utils.ErrBytes(err), nil
return false, MintAssetComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
if err := storage.SetAsset(ctx, mu, m.Asset, symbol, decimals, metadata, newSupply, actor); err != nil {
return false, MintAssetComputeUnits, utils.ErrBytes(err), nil
return false, MintAssetComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
if err := storage.AddBalance(ctx, mu, m.To, m.Asset, m.Value, true); err != nil {
return false, MintAssetComputeUnits, utils.ErrBytes(err), nil
return false, MintAssetComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
return true, MintAssetComputeUnits, nil, nil
return true, MintAssetComputeUnits, [][]byte{{}}, nil
}

func (*MintAsset) MaxComputeUnits(chain.Rules) uint64 {
Expand Down
12 changes: 6 additions & 6 deletions examples/tokenvm/actions/transfer.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,21 @@ func (t *Transfer) Execute(
_ int64,
actor codec.Address,
_ codec.LID,
) (bool, uint64, []byte, error) {
) (bool, uint64, [][]byte, error) {
if t.Value == 0 {
return false, TransferComputeUnits, OutputValueZero, nil
return false, TransferComputeUnits, [][]byte{OutputValueZero}, nil
}
if len(t.Memo) > MaxMemoSize {
return false, CreateAssetComputeUnits, OutputMemoTooLarge, nil
return false, CreateAssetComputeUnits, [][]byte{OutputMemoTooLarge}, nil
}
if err := storage.SubBalance(ctx, mu, actor, t.Asset, t.Value); err != nil {
return false, TransferComputeUnits, utils.ErrBytes(err), nil
return false, TransferComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
// TODO: allow sender to configure whether they will pay to create
if err := storage.AddBalance(ctx, mu, t.To, t.Asset, t.Value, true); err != nil {
return false, TransferComputeUnits, utils.ErrBytes(err), nil
return false, TransferComputeUnits, [][]byte{utils.ErrBytes(err)}, nil
}
return true, TransferComputeUnits, nil, nil
return true, TransferComputeUnits, [][]byte{{}}, nil
}

func (*Transfer) MaxComputeUnits(chain.Rules) uint64 {
Expand Down
21 changes: 12 additions & 9 deletions examples/tokenvm/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,16 +194,19 @@ func (c *Controller) Accepted(ctx context.Context, blk *chain.StatelessBlock) er
c.orderBook.Add(action.GetActionID(uint8(i), tx.ID()), tx.Auth.Actor(), action)
case *actions.FillOrder:
c.metrics.fillOrder.Inc()
orderResult, err := actions.UnmarshalOrderResult(result.Output)
if err != nil {
// This should never happen
return err
outputs := result.Outputs[i]
for _, output := range outputs {
orderResult, err := actions.UnmarshalOrderResult(output)
if err != nil {
// This should never happen
return err
}
if orderResult.Remaining == 0 {
c.orderBook.Remove(action.Order)
continue
}
c.orderBook.UpdateRemaining(action.Order, orderResult.Remaining)
}
if orderResult.Remaining == 0 {
c.orderBook.Remove(action.Order)
continue
}
c.orderBook.UpdateRemaining(action.Order, orderResult.Remaining)
case *actions.CloseOrder:
c.metrics.closeOrder.Inc()
c.orderBook.Remove(action.Order)
Expand Down
Loading

0 comments on commit bd97396

Please sign in to comment.