Skip to content

Commit

Permalink
Merge pull request #3522 from iotaledger/fix_wasp_cli_output_consumption
Browse files Browse the repository at this point in the history
Fix wasp-cli request sending
  • Loading branch information
lmoe authored Jan 15, 2025
2 parents 11aad3f + e33c3bd commit de3c619
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 33 deletions.
23 changes: 21 additions & 2 deletions clients/chainclient/chainclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"math"

iotago "github.com/iotaledger/iota.go/v3"

"github.com/iotaledger/wasp/clients/apiclient"
"github.com/iotaledger/wasp/clients/apiextensions"
"github.com/iotaledger/wasp/packages/cryptolib"
Expand Down Expand Up @@ -47,6 +48,7 @@ type PostRequestParams struct {
Allowance *isc.Assets
gasBudget uint64
AutoAdjustStorageDeposit bool
OnlyUnlockedOutputs bool
}

func (par *PostRequestParams) GasBudget() uint64 {
Expand All @@ -69,7 +71,16 @@ func (c *Client) Post1Request(
entryPoint isc.Hname,
params ...PostRequestParams,
) (*iotago.Transaction, error) {
outputsSet, err := c.Layer1Client.OutputMap(c.KeyPair.Address())
par := defaultParams(params...)
var outputsSet iotago.OutputSet
var err error

if par.OnlyUnlockedOutputs {
outputsSet, err = c.Layer1Client.OutputMapNonLocked(c.KeyPair.Address())
} else {
outputsSet, err = c.Layer1Client.OutputMap(c.KeyPair.Address())
}

if err != nil {
return nil, err
}
Expand All @@ -83,8 +94,16 @@ func (c *Client) PostNRequests(
requestsCount int,
params ...PostRequestParams,
) ([]*iotago.Transaction, error) {
par := defaultParams(params...)
var outputs iotago.OutputSet
var err error
outputs, err := c.Layer1Client.OutputMap(c.KeyPair.Address())

if par.OnlyUnlockedOutputs {
outputs, err = c.Layer1Client.OutputMapNonLocked(c.KeyPair.Address())
} else {
outputs, err = c.Layer1Client.OutputMap(c.KeyPair.Address())
}

if err != nil {
return nil, err
}
Expand Down
77 changes: 47 additions & 30 deletions packages/l1connection/l1connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,17 @@ type Config struct {
}

type Client interface {
// requests funds from faucet, waits for confirmation
// RequestFunds requests funds from faucet, waits for confirmation
RequestFunds(addr iotago.Address, timeout ...time.Duration) error
// sends a tx (including tipselection and local PoW if necessary) and waits for confirmation
// PostTxAndWaitUntilConfirmation sends a tx (including tipselection and local PoW if necessary) and waits for confirmation
PostTxAndWaitUntilConfirmation(tx *iotago.Transaction, timeout ...time.Duration) (iotago.BlockID, error)
// returns the outputs owned by a given address
// OutputMap returns the outputs owned by a given address
OutputMap(myAddress iotago.Address, timeout ...time.Duration) (iotago.OutputSet, error)
// output
// OutputMapNonLocked returns the outputs owned by a given address, excluding any locked outputs (mainly relevant for sending TXs from clients)
OutputMapNonLocked(myAddress iotago.Address, timeout ...time.Duration) (iotago.OutputSet, error)
// GetAliasOutput output
GetAliasOutput(aliasID iotago.AliasID, timeout ...time.Duration) (iotago.OutputID, iotago.Output, error)
// used to query the health endpoint of the node
// Health used to query the health endpoint of the node
Health(timeout ...time.Duration) (bool, error)
}

Expand Down Expand Up @@ -87,8 +89,31 @@ func NewClient(config Config, log *logger.Logger, timeout ...time.Duration) Clie
}
}

// OutputMap implements L1Connection
func (c *l1client) OutputMap(myAddress iotago.Address, timeout ...time.Duration) (iotago.OutputSet, error) {
func (c *l1client) readOutputs(ctx context.Context, queries []nodeclient.IndexerQuery) (iotago.OutputSet, error) {
result := make(map[iotago.OutputID]iotago.Output)

for _, query := range queries {
res, err := c.indexerClient.Outputs(ctx, query)
if err != nil {
return nil, fmt.Errorf("failed to query address outputs: %w", err)
}
for res.Next() {
outputs, err := res.Outputs()
if err != nil {
return nil, fmt.Errorf("failed to fetch address outputs: %w", err)
}

outputIDs := res.Response.Items.MustOutputIDs()
for i := range outputs {
result[outputIDs[i]] = outputs[i]
}
}
}
return result, nil
}

// OutputMapNonLocked implements L1Connection
func (c *l1client) OutputMapNonLocked(myAddress iotago.Address, timeout ...time.Duration) (iotago.OutputSet, error) {
ctxWithTimeout, cancelContext := newCtx(c.ctx, timeout...)
defer cancelContext()

Expand All @@ -103,44 +128,36 @@ func (c *l1client) OutputMap(myAddress iotago.Address, timeout ...time.Duration)
HasTimelock: &trueParam,
TimelockedBefore: uint32(time.Now().Unix()),
},
IndexerNativeTokenParas: nodeclient.IndexerNativeTokenParas{
HasNativeTokens: &falseParam,
},
},
&nodeclient.BasicOutputsQuery{
AddressBech32: bech32Addr,
IndexerTimelockParas: nodeclient.IndexerTimelockParas{
HasTimelock: &falseParam,
},
IndexerNativeTokenParas: nodeclient.IndexerNativeTokenParas{
HasNativeTokens: &falseParam,
},
},
&nodeclient.FoundriesQuery{AliasAddressBech32: bech32Addr},
&nodeclient.NFTsQuery{AddressBech32: bech32Addr},
&nodeclient.AliasesQuery{GovernorBech32: bech32Addr},
}

result := make(map[iotago.OutputID]iotago.Output)
return c.readOutputs(ctxWithTimeout, queries)
}

for _, query := range queries {
res, err := c.indexerClient.Outputs(ctxWithTimeout, query)
if err != nil {
return nil, fmt.Errorf("failed to query address outputs: %w", err)
}
for res.Next() {
outputs, err := res.Outputs()
if err != nil {
return nil, fmt.Errorf("failed to fetch address outputs: %w", err)
}
// OutputMap implements L1Connection
func (c *l1client) OutputMap(myAddress iotago.Address, timeout ...time.Duration) (iotago.OutputSet, error) {
ctxWithTimeout, cancelContext := newCtx(c.ctx, timeout...)
defer cancelContext()

outputIDs := res.Response.Items.MustOutputIDs()
for i := range outputs {
result[outputIDs[i]] = outputs[i]
}
}
bech32Addr := myAddress.Bech32(parameters.L1().Protocol.Bech32HRP)

queries := []nodeclient.IndexerQuery{
&nodeclient.BasicOutputsQuery{AddressBech32: bech32Addr},
&nodeclient.FoundriesQuery{AliasAddressBech32: bech32Addr},
&nodeclient.NFTsQuery{AddressBech32: bech32Addr},
&nodeclient.AliasesQuery{GovernorBech32: bech32Addr},
}
return result, nil

return c.readOutputs(ctxWithTimeout, queries)
}

// postBlock sends a block (including tipselection and local PoW if necessary).
Expand Down
9 changes: 9 additions & 0 deletions tools/cluster/tests/wasp-cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/stretchr/testify/require"

iotago "github.com/iotaledger/iota.go/v3"

"github.com/iotaledger/wasp/clients/apiclient"
"github.com/iotaledger/wasp/packages/kv/codec"
"github.com/iotaledger/wasp/packages/parameters"
Expand Down Expand Up @@ -203,6 +204,14 @@ func TestWaspCLIDeposit(t *testing.T) {
)
require.Regexp(t, `.*Error: \(empty\).*`, strings.Join(out, ""))

out = w.MustRun("balance")
for _, line := range out {
if strings.Contains(line, "0x") {
balance := strings.TrimSpace(strings.Split(line, ":")[1])
require.Equal(t, balance, "2")
}
}

// deposit the native token to the chain (to an ethereum account)
w.MustRun(
"chain", "deposit", eth.String(),
Expand Down
3 changes: 2 additions & 1 deletion tools/wasp-cli/chain/postrequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"github.com/spf13/cobra"

iotago "github.com/iotaledger/iota.go/v3"

"github.com/iotaledger/wasp/clients/chainclient"
"github.com/iotaledger/wasp/packages/isc"
"github.com/iotaledger/wasp/packages/transaction"
Expand Down Expand Up @@ -46,7 +47,7 @@ func postRequest(nodeName, chain, hname, fname string, params chainclient.PostRe
}

util.WithSCTransaction(config.GetChain(chain), nodeName, func() (*iotago.Transaction, error) {
return scClient.PostRequest(fname, params)
return scClient.PostRequest(fname, params, chainclient.PostRequestParams{OnlyUnlockedOutputs: true})
})
}

Expand Down

0 comments on commit de3c619

Please sign in to comment.