diff --git a/channel/funder.go b/channel/funder.go index 5b82529..ffc80a4 100644 --- a/channel/funder.go +++ b/channel/funder.go @@ -199,18 +199,17 @@ func (f *Funder) openChannel(ctx context.Context, req pchannel.FundingReq) error } func (f *Funder) FundChannel(ctx context.Context, state *pchannel.State, funderIdx bool) error { - balsStellar, err := wire.MakeBalances(state.Allocation) log.Println("Funding channel with balances: ", balsStellar) if err != nil { return errors.New("error while making balances") } - if !balsStellar.Tokens.Equals(&f.assetAddrs) { + if !containsAllAssets(balsStellar.Tokens, f.assetAddrs) { log.Println(balsStellar.Tokens, f.assetAddrs) return errors.New("asset address is not equal to the address stored in the state") } - + log.Println(f.perunAddr, state.ID, funderIdx) return f.cb.Fund(ctx, f.perunAddr, state.ID, funderIdx) } @@ -238,3 +237,25 @@ func makeTimeoutErr(remains []pchannel.Index, assetIdx int) error { }}, ) } + +// Function to check if all assets in state.Allocation are present in f.assetAddrs +func containsAllAssets(stateAssets xdr.ScVec, fAssets xdr.ScVec) bool { + fAssetSet := assetSliceToSet(fAssets) + + for _, asset := range stateAssets { + if _, found := fAssetSet[asset.String()]; !found { + return false + } + } + + return true +} + +// Helper function to convert a slice of xdr.Asset to a set (map for fast lookup) +func assetSliceToSet(assets xdr.ScVec) map[string]struct{} { + assetSet := make(map[string]struct{}) + for _, asset := range assets { + assetSet[asset.String()] = struct{}{} + } + return assetSet +} diff --git a/client/client.go b/client/client.go index a1304b0..a965fe7 100644 --- a/client/client.go +++ b/client/client.go @@ -23,7 +23,6 @@ import ( "log" pchannel "perun.network/go-perun/channel" pwallet "perun.network/go-perun/wallet" - "perun.network/perun-stellar-backend/channel/types" "perun.network/perun-stellar-backend/event" "perun.network/perun-stellar-backend/wire" ) @@ -265,8 +264,9 @@ func (cb *ContractBackend) GetChannelInfo(ctx context.Context, perunAddr xdr.ScA if err != nil { return wire.Channel{}, errors.New("error while building get_channel tx") } - chanInfo, err := cb.InvokeUnsignedTx("get_channel", getchTxArgs, perunAddr) + chanInfo, _, err := cb.InvokeUnsignedTx("get_channel", getchTxArgs, perunAddr) if err != nil { + log.Println(err) return wire.Channel{}, errors.New("error while processing and submitting get_channel tx") } diff --git a/client/contractbackend.go b/client/contractbackend.go index 14117ff..9440f1e 100644 --- a/client/contractbackend.go +++ b/client/contractbackend.go @@ -120,11 +120,11 @@ func (cb *ContractBackend) GetBalance(cID xdr.ScAddress) (string, error) { if err != nil { return "", err } - tx, err := cb.InvokeSignedTx("balance", TokenNameArgs, cID) + _, bal, err := cb.InvokeUnsignedTx("balance", TokenNameArgs, cID) if err != nil { return "", err } - return tx.V3.SorobanMeta.ReturnValue.String(), nil + return bal, nil } func (st *StellarSigner) GetHorizonAccount() (horizon.Account, error) { @@ -158,28 +158,24 @@ func (st *StellarSigner) GetHorizonClient() *horizonclient.Client { return st.hzClient } -func (c *ContractBackend) InvokeUnsignedTx(fname string, callTxArgs xdr.ScVec, contractAddr xdr.ScAddress) (wire.Channel, error) { //xdr.TransactionMeta, error +func (c *ContractBackend) InvokeUnsignedTx(fname string, callTxArgs xdr.ScVec, contractAddr xdr.ScAddress) (wire.Channel, string, error) { //xdr.TransactionMeta, error c.cbMutex.Lock() defer c.cbMutex.Unlock() fnameXdr := xdr.ScSymbol(fname) hzAcc, err := c.tr.GetHorizonAccount() if err != nil { - return wire.Channel{}, err + return wire.Channel{}, "", err } hzClient := c.tr.GetHorizonClient() - txSender, ok := c.tr.sender.(*TxSender) - if !ok { - return wire.Channel{}, errors.New("sender is not of type *TxSender") - } - - txSender.SetHzClient(hzClient) + c.tr.sender.SetHzClient(hzClient) + chanInf := fname == "get_channel" invokeHostFunctionOp := BuildContractCallOp(hzAcc, fnameXdr, callTxArgs, contractAddr) - chanInfo, _, _ := PreflightHostFunctionsResult(hzClient, &hzAcc, *invokeHostFunctionOp) + chanInfo, bal, _, _ := PreflightHostFunctionsResult(hzClient, &hzAcc, *invokeHostFunctionOp, chanInf) - return chanInfo, nil + return chanInfo, bal, nil } func (c *ContractBackend) InvokeSignedTx(fname string, callTxArgs xdr.ScVec, contractAddr xdr.ScAddress) (xdr.TransactionMeta, error) { @@ -195,9 +191,9 @@ func (c *ContractBackend) InvokeSignedTx(fname string, callTxArgs xdr.ScVec, con c.tr.sender.SetHzClient(hzClient) invokeHostFunctionOp := BuildContractCallOp(hzAcc, fnameXdr, callTxArgs, contractAddr) - preFlightOp, _ := PreflightHostFunctions(hzClient, &hzAcc, *invokeHostFunctionOp) - minFeeCustom := int64(500000) - txParams := GetBaseTransactionParamsWithFee(&hzAcc, minFeeCustom, &preFlightOp) + preFlightOp, minFee := PreflightHostFunctions(hzClient, &hzAcc, *invokeHostFunctionOp) + minFeeCustom := int64(100) + txParams := GetBaseTransactionParamsWithFee(&hzAcc, minFee+minFeeCustom, &preFlightOp) txUnsigned, err := txnbuild.NewTransaction(txParams) if err != nil { return xdr.TransactionMeta{}, err diff --git a/client/hzclient.go b/client/hzclient.go index 6a91b18..b3edbf8 100644 --- a/client/hzclient.go +++ b/client/hzclient.go @@ -5,8 +5,8 @@ import ( "github.com/stellar/go/keypair" ) -const HorizonURL = "http://localhost:8000" -const NETWORK_PASSPHRASE = "Standalone Network ; February 2017" +const HorizonURL = "https://horizon-testnet.stellar.org" +const NETWORK_PASSPHRASE = "Test SDF Network ; September 2015" func NewHorizonClient() *horizonclient.Client { return &horizonclient.Client{HorizonURL: HorizonURL} diff --git a/client/transaction.go b/client/transaction.go index 167c0b0..e9106ed 100644 --- a/client/transaction.go +++ b/client/transaction.go @@ -8,12 +8,16 @@ import ( "github.com/stellar/go/protocols/horizon" "github.com/stellar/go/txnbuild" "github.com/stellar/go/xdr" + "log" + "math/big" "perun.network/perun-stellar-backend/wire" - "strconv" "time" ) -const sorobanRPCPort = 8000 +const ( + sorobanRPCLink = "http://localhost:8000/soroban/rpc" + sorobanTestnet = "https://soroban-testnet.stellar.org" +) func (st *StellarSigner) createSignedTxFromParams(txParams txnbuild.TransactionParams) (*txnbuild.Transaction, error) { @@ -98,8 +102,8 @@ func PreflightHostFunctions(hzClient *horizonclient.Client, } func PreflightHostFunctionsResult(hzClient *horizonclient.Client, - sourceAccount txnbuild.Account, function txnbuild.InvokeHostFunction, -) (wire.Channel, txnbuild.InvokeHostFunction, int64) { + sourceAccount txnbuild.Account, function txnbuild.InvokeHostFunction, chInfo bool, +) (wire.Channel, string, txnbuild.InvokeHostFunction, int64) { result, transactionData := simulateTransaction(hzClient, sourceAccount, &function) function.Ext = xdr.TransactionExt{ @@ -117,21 +121,32 @@ func PreflightHostFunctionsResult(hzClient *horizonclient.Client, if err != nil { panic(err) } + log.Println("RESULT: ", decodedXdr) + if chInfo { + decChanInfo := decodedXdr - decChanInfo := decodedXdr + if decChanInfo.Type != xdr.ScValTypeScvMap { + return getChan, "", function, result.MinResourceFee - if decChanInfo.Type != xdr.ScValTypeScvMap { - return getChan, function, result.MinResourceFee + } - } + err = getChan.FromScVal(decChanInfo) + if err != nil { - err = getChan.FromScVal(decChanInfo) - if err != nil { + panic(err) + } - panic(err) + return getChan, "", function, result.MinResourceFee + } else { + i128 := decodedXdr.MustI128() + hi := big.NewInt(int64(i128.Hi)) + lo := big.NewInt(int64(i128.Lo)) + + // Combine hi and lo into a single big.Int + combined := hi.Lsh(hi, 64).Or(hi, lo) + return wire.Channel{}, combined.String(), function, result.MinResourceFee } - return getChan, function, result.MinResourceFee } func simulateTransaction(hzClient *horizonclient.Client, @@ -144,7 +159,7 @@ func simulateTransaction(hzClient *horizonclient.Client, } syncWithSorobanRPC(uint32(root.HorizonSequence)) - ch := jhttp.NewChannel("http://localhost:"+strconv.Itoa(sorobanRPCPort)+"/soroban/rpc", nil) + ch := jhttp.NewChannel(sorobanTestnet, nil) sorobanRPCClient := jrpc2.NewClient(ch, nil) txParams := GetBaseTransactionParamsWithFee(sourceAccount, txnbuild.MinBaseFee, op) txParams.IncrementSequenceNum = false @@ -175,7 +190,7 @@ func syncWithSorobanRPC(ledgerToWaitFor uint32) { result := struct { Sequence uint32 `json:"sequence"` }{} - ch := jhttp.NewChannel("http://localhost:"+strconv.Itoa(sorobanRPCPort)+"/soroban/rpc", nil) + ch := jhttp.NewChannel(sorobanTestnet, nil) sorobanRPCClient := jrpc2.NewClient(ch, nil) err := sorobanRPCClient.CallResult(context.Background(), "getLatestLedger", nil, &result) if err != nil {