From 3ae35948b79dcbddb5bf971e730bf07fff6f2acf Mon Sep 17 00:00:00 2001 From: jtieri Date: Fri, 4 Aug 2023 14:11:02 -0500 Subject: [PATCH] WIP: working on testing local transfers on penumbra --- chain/penumbra/penumbra_app_node.go | 6 +++- chain/penumbra/penumbra_client_node.go | 38 ++++++++++++++++----- chain/penumbra/penumbra_client_node_test.go | 23 +++++++++++++ examples/penumbra/penumbra_chain_test.go | 33 ++++++++++++++++-- 4 files changed, 88 insertions(+), 12 deletions(-) create mode 100644 chain/penumbra/penumbra_client_node_test.go diff --git a/chain/penumbra/penumbra_app_node.go b/chain/penumbra/penumbra_app_node.go index 4e9341e9e..f0430ab39 100644 --- a/chain/penumbra/penumbra_app_node.go +++ b/chain/penumbra/penumbra_app_node.go @@ -227,11 +227,14 @@ func (p *PenumbraAppNode) GenerateGenesisFile( func (p *PenumbraAppNode) GetAddress(ctx context.Context, keyName string) ([]byte, error) { keyPath := filepath.Join(p.HomeDir(), "keys", keyName) - cmd := []string{"pcli", "-d", keyPath, "view", "address"} + pdUrl := fmt.Sprintf("http://%s:8080", p.HostName()) + cmd := []string{"pcli", "-d", keyPath, "-n", pdUrl, "view", "address"} + stdout, _, err := p.Exec(ctx, cmd, nil) if err != nil { return nil, err } + addresses := strings.Split(string(stdout), "\n") for _, address := range addresses { fields := strings.Fields(address) @@ -243,6 +246,7 @@ func (p *PenumbraAppNode) GetAddress(ctx context.Context, keyName string) ([]byt return []byte(fields[2]), nil } } + return []byte{}, errors.New("address not found") } diff --git a/chain/penumbra/penumbra_client_node.go b/chain/penumbra/penumbra_client_node.go index 9a7df2c3a..ad20be8bb 100644 --- a/chain/penumbra/penumbra_client_node.go +++ b/chain/penumbra/penumbra_client_node.go @@ -139,21 +139,18 @@ func (p *PenumbraClientNode) SendFunds(ctx context.Context, amount ibc.WalletAmo } defer channel.Close() + hi, lo := translateBigInt(amount.Amount) + // 5.1. Generate a transaction plan sending funds to an address. tpr := &viewv1alpha1.TransactionPlannerRequest{ //XAccountGroupId: nil, Outputs: []*viewv1alpha1.TransactionPlannerRequest_Output{{ Value: &cryptov1alpha1.Value{ Amount: &cryptov1alpha1.Amount{ - // TODO: this is incorrect, we need to take a 128-bit int and break it into the hi/lo parts before - // building the tx plan - Lo: amount.Amount.Uint64(), - Hi: amount.Amount.Uint64(), + Lo: lo, + Hi: hi, }, - // TODO: this should be the AssetID and not the denom string. One option is to make a mapping - // of DenomID->Denom Strings or see if we can get a change server side for this as well like the balance - // change we discussed. - AssetId: &cryptov1alpha1.AssetId{Inner: []byte(amount.Denom)}, + AssetId: &cryptov1alpha1.AssetId{AltBaseDenom: amount.Denom}, }, Address: &cryptov1alpha1.Address{Inner: []byte(amount.Address)}, }}, @@ -304,6 +301,31 @@ func translateHiAndLo(hi, lo uint64) math.Int { return math.NewIntFromBigInt(i) } +// translateBigInt converts a Cosmos SDK Int, which is a wrapper around Go's big.Int, into two uint64 values +func translateBigInt(i math.Int) (uint64, uint64) { + bz := i.BigInt().Bytes() + + // Pad the byte slice with leading zeros to ensure it's 16 bytes long + paddedBytes := make([]byte, 16) + copy(paddedBytes[16-len(bz):], bz) + + // Extract the high and low parts from the padded byte slice + var hi uint64 + var lo uint64 + + for j := 0; j < 8; j++ { + hi <<= 8 + hi |= uint64(paddedBytes[j]) + } + + for j := 8; j < 16; j++ { + lo <<= 8 + lo |= uint64(paddedBytes[j]) + } + + return hi, lo +} + // GetDenomMetadata invokes a gRPC request to obtain the DenomMetadata for a specified asset ID. func (p *PenumbraClientNode) GetDenomMetadata(ctx context.Context, assetId *cryptov1alpha1.AssetId) (*cryptov1alpha1.DenomMetadata, error) { channel, err := grpc.Dial( diff --git a/chain/penumbra/penumbra_client_node_test.go b/chain/penumbra/penumbra_client_node_test.go new file mode 100644 index 000000000..edfb73b41 --- /dev/null +++ b/chain/penumbra/penumbra_client_node_test.go @@ -0,0 +1,23 @@ +package penumbra + +import ( + "math/big" + "testing" + + "cosmossdk.io/math" + "github.com/stretchr/testify/require" +) + +func TestBigIntDecoding(t *testing.T) { + bigInt := math.NewInt(11235813) + hi, lo := translateBigInt(bigInt) + converted := translateHiAndLo(hi, lo) + require.True(t, bigInt.Equal(converted)) + + b := big.NewInt(0) + b.SetString("18446744073709551620", 10) // use a number that is bigger than the maximum value an uint64 can hold + bInt := math.NewIntFromBigInt(b) + hi, lo = translateBigInt(bInt) + converted = translateHiAndLo(hi, lo) + require.True(t, converted.Equal(bInt)) +} diff --git a/examples/penumbra/penumbra_chain_test.go b/examples/penumbra/penumbra_chain_test.go index 2bc627c06..8862f129b 100644 --- a/examples/penumbra/penumbra_chain_test.go +++ b/examples/penumbra/penumbra_chain_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "cosmossdk.io/math" "github.com/strangelove-ventures/interchaintest/v7" "github.com/strangelove-ventures/interchaintest/v7/chain/penumbra" "github.com/strangelove-ventures/interchaintest/v7/ibc" @@ -52,10 +53,36 @@ func TestPenumbraChainStart(t *testing.T) { require.NoError(t, err, "penumbra chain failed to make blocks") - node := chain.(*penumbra.PenumbraChain).PenumbraNodes[0] + alice := chain.(*penumbra.PenumbraChain).PenumbraNodes[0] + bob := chain.(*penumbra.PenumbraChain).PenumbraNodes[1] - bal, err := chain.GetBalance(ctx, node.PenumbraClientNodes["validator"].KeyName, chain.Config().Denom) + aliceBal, err := chain.GetBalance(ctx, alice.PenumbraClientNodes["validator"].KeyName, chain.Config().Denom) + //require.NoError(t, err) + + bobBal, err := chain.GetBalance(ctx, bob.PenumbraClientNodes["validator"].KeyName, chain.Config().Denom) + //require.NoError(t, err) + + t.Logf("Alice Balance: %s \n", aliceBal) + t.Logf("Bob Balance: %s \n", bobBal) + + //bobAddr, err := bob.PenumbraAppNode.GetAddress(ctx, bob.PenumbraClientNodes["validator"].KeyName) + //require.NoError(t, err) + + transfer := ibc.WalletAmount{ + Address: bob.PenumbraClientNodes["validator"].KeyName, + Denom: chain.Config().Denom, + Amount: math.NewInt(1_000), + } + + err = chain.SendFunds(ctx, alice.PenumbraClientNodes["validator"].KeyName, transfer) require.NoError(t, err) - t.Logf("Balance: %d \n", bal) + aliceBal, err = chain.GetBalance(ctx, alice.PenumbraClientNodes["validator"].KeyName, chain.Config().Denom) + //require.NoError(t, err) + + bobBal, err = chain.GetBalance(ctx, bob.PenumbraClientNodes["validator"].KeyName, chain.Config().Denom) + //require.NoError(t, err) + + t.Logf("Alice Balance: %s \n", aliceBal) + t.Logf("Bob Balance: %s \n", bobBal) }