From 3180970d99e1c6f2d3b275756ad44ef9675ada3b Mon Sep 17 00:00:00 2001 From: Tal Derei Date: Wed, 18 Dec 2024 10:44:45 -0800 Subject: [PATCH 01/19] add t-addr support to view service --- apps/minifront/src/state/ibc-out.ts | 17 +++- packages/protobuf/package.json | 2 +- packages/services/src/view-service/index.ts | 2 + .../src/view-service/transparent-address.ts | 18 ++++ packages/wasm/crate/Cargo.lock | 91 ++++++++++--------- packages/wasm/crate/Cargo.toml | 30 +++--- packages/wasm/crate/src/keys.rs | 21 +++++ packages/wasm/crate/tests/test_metadata.rs | 1 + packages/wasm/src/keys.ts | 10 ++ 9 files changed, 131 insertions(+), 61 deletions(-) create mode 100644 packages/services/src/view-service/transparent-address.ts diff --git a/apps/minifront/src/state/ibc-out.ts b/apps/minifront/src/state/ibc-out.ts index 5a37e29c26..0c7453ed17 100644 --- a/apps/minifront/src/state/ibc-out.ts +++ b/apps/minifront/src/state/ibc-out.ts @@ -2,6 +2,7 @@ import { AllSlices, SliceCreator, useStore } from '.'; import { BalancesResponse, TransactionPlannerRequest, + TransparentAddressRequest, } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb'; import { BigNumber } from 'bignumber.js'; import { ClientState } from '@penumbra-zone/protobuf/ibc/lightclients/tendermint/v1/tendermint_pb'; @@ -32,6 +33,7 @@ import { IbcConnectionService, ViewService, } from '@penumbra-zone/protobuf'; +import { PartialMessage } from '@bufbuild/protobuf'; export const { chains, useChains } = createZQuery({ name: 'chains', @@ -215,6 +217,18 @@ const getPlanRequest = async ({ const { timeoutHeight, timeoutTime } = await getTimeout(chain.channelId); + // Request transparent address from view service + const { address: t_addr, encoding: _encoding } = await penumbra + .service(ViewService) + .transparentAddress(new TransparentAddressRequest({})); + if (!t_addr) { + throw new Error('Error with generating IBC transparent address'); + } + + // Detect USDC Noble withdrawals, and use transparent (t-addr) addresses + // to ensure compatibility. Prepare the ICS20 withdrawal messages with the t-addr + // flag set to 'true' + return new TransactionPlannerRequest({ ics20Withdrawals: [ { @@ -228,7 +242,8 @@ const getPlanRequest = async ({ timeoutHeight, timeoutTime, sourceChannel: chain.channelId, - useCompatAddress: bech32ChainIds.includes(chain.chainId), + useCompatAddress: false, + useTransparentAddress: true, // temporarily hardcoding for testing purposes }, ], source: addressIndex, diff --git a/packages/protobuf/package.json b/packages/protobuf/package.json index 5852db7d8c..de4d1d9697 100644 --- a/packages/protobuf/package.json +++ b/packages/protobuf/package.json @@ -16,7 +16,7 @@ "gen:ibc": "buf generate buf.build/cosmos/ibc:7ab44ae956a0488ea04e04511efa5f70", "gen:ics23": "buf generate buf.build/cosmos/ics23:55085f7c710a45f58fa09947208eb70b", "gen:noble": "buf generate buf.build/noble-assets/forwarding:5a8609a6772d417584a9c60cd8b80881", - "gen:penumbra": "buf generate buf.build/penumbra-zone/penumbra:37cef73133644d9dbdeae95b644db3ec", + "gen:penumbra": "buf generate buf.build/penumbra-zone/penumbra:0a56a4f32c244e7eb277e02f6e85afbd", "lint": "eslint src", "lint:fix": "eslint src --fix", "lint:strict": "tsc --noEmit && eslint src --max-warnings 0", diff --git a/packages/services/src/view-service/index.ts b/packages/services/src/view-service/index.ts index 2d9f11259b..4b48874c98 100644 --- a/packages/services/src/view-service/index.ts +++ b/packages/services/src/view-service/index.ts @@ -29,6 +29,7 @@ import { unclaimedSwaps } from './unclaimed-swaps.js'; import { walletId } from './wallet-id.js'; import { witness } from './witness.js'; import { witnessAndBuild } from './witness-and-build.js'; +import { transparentAddress } from './transparent-address.js'; export type Impl = ServiceImpl; @@ -62,4 +63,5 @@ export const viewImpl: Impl = { walletId, witness, witnessAndBuild, + transparentAddress, }; diff --git a/packages/services/src/view-service/transparent-address.ts b/packages/services/src/view-service/transparent-address.ts new file mode 100644 index 0000000000..c91bb104eb --- /dev/null +++ b/packages/services/src/view-service/transparent-address.ts @@ -0,0 +1,18 @@ +import type { Impl } from './index.js'; +import { fvkCtx } from '../ctx/full-viewing-key.js'; +import { getTransparentAddress } from '@penumbra-zone/wasm/keys'; + +export const transparentAddress: Impl['transparentAddress'] = async (_, ctx) => { + const fvk = await ctx.values.get(fvkCtx)(); + const t_addr = getTransparentAddress(fvk); + + return { + address: t_addr.address, + encoding: t_addr.encoding, + }; + + // return new TransparentAddressResponse({ + // address: t_addr.address, + // encoding: t_addr.encoding, + // }); +}; diff --git a/packages/wasm/crate/Cargo.lock b/packages/wasm/crate/Cargo.lock index b814453641..8dc5376d59 100644 --- a/packages/wasm/crate/Cargo.lock +++ b/packages/wasm/crate/Cargo.lock @@ -804,8 +804,8 @@ dependencies = [ [[package]] name = "decaf377-fmd" -version = "0.80.5" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=5e8ea2b12777e5956db6ea5c620877e5d1aa2de5#5e8ea2b12777e5956db6ea5c620877e5d1aa2de5" +version = "0.81.0" +source = "git+https://github.com/penumbra-zone/penumbra.git?tag=v0.81.0#8df36a4247ae90acc8aecc48bfa37e55785f779f" dependencies = [ "ark-ff", "ark-serialize", @@ -818,8 +818,8 @@ dependencies = [ [[package]] name = "decaf377-ka" -version = "0.80.5" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=5e8ea2b12777e5956db6ea5c620877e5d1aa2de5#5e8ea2b12777e5956db6ea5c620877e5d1aa2de5" +version = "0.81.0" +source = "git+https://github.com/penumbra-zone/penumbra.git?tag=v0.81.0#8df36a4247ae90acc8aecc48bfa37e55785f779f" dependencies = [ "ark-ff", "decaf377", @@ -1043,8 +1043,9 @@ dependencies = [ [[package]] name = "f4jumble" -version = "0.0.0" -source = "git+https://github.com/zcash/librustzcash?rev=2425a0869098e3b0588ccd73c42716bcf418612c#2425a0869098e3b0588ccd73c42716bcf418612c" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d42773cb15447644d170be20231a3268600e0c4cea8987d013b93ac973d3cf7" dependencies = [ "blake2b_simd 1.0.2", ] @@ -2103,8 +2104,8 @@ dependencies = [ [[package]] name = "penumbra-asset" -version = "0.80.5" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=5e8ea2b12777e5956db6ea5c620877e5d1aa2de5#5e8ea2b12777e5956db6ea5c620877e5d1aa2de5" +version = "0.81.0" +source = "git+https://github.com/penumbra-zone/penumbra.git?tag=v0.81.0#8df36a4247ae90acc8aecc48bfa37e55785f779f" dependencies = [ "anyhow", "ark-ff", @@ -2121,6 +2122,7 @@ dependencies = [ "decaf377-rdsa", "derivative", "ethnum", + "getrandom", "hex", "ibig", "num-bigint", @@ -2141,8 +2143,8 @@ dependencies = [ [[package]] name = "penumbra-auction" -version = "0.80.5" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=5e8ea2b12777e5956db6ea5c620877e5d1aa2de5#5e8ea2b12777e5956db6ea5c620877e5d1aa2de5" +version = "0.81.0" +source = "git+https://github.com/penumbra-zone/penumbra.git?tag=v0.81.0#8df36a4247ae90acc8aecc48bfa37e55785f779f" dependencies = [ "anyhow", "ark-ff", @@ -2186,8 +2188,8 @@ dependencies = [ [[package]] name = "penumbra-community-pool" -version = "0.80.5" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=5e8ea2b12777e5956db6ea5c620877e5d1aa2de5#5e8ea2b12777e5956db6ea5c620877e5d1aa2de5" +version = "0.81.0" +source = "git+https://github.com/penumbra-zone/penumbra.git?tag=v0.81.0#8df36a4247ae90acc8aecc48bfa37e55785f779f" dependencies = [ "anyhow", "ark-ff", @@ -2216,8 +2218,8 @@ dependencies = [ [[package]] name = "penumbra-compact-block" -version = "0.80.5" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=5e8ea2b12777e5956db6ea5c620877e5d1aa2de5#5e8ea2b12777e5956db6ea5c620877e5d1aa2de5" +version = "0.81.0" +source = "git+https://github.com/penumbra-zone/penumbra.git?tag=v0.81.0#8df36a4247ae90acc8aecc48bfa37e55785f779f" dependencies = [ "anyhow", "ark-ff", @@ -2247,8 +2249,8 @@ dependencies = [ [[package]] name = "penumbra-dex" -version = "0.80.5" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=5e8ea2b12777e5956db6ea5c620877e5d1aa2de5#5e8ea2b12777e5956db6ea5c620877e5d1aa2de5" +version = "0.81.0" +source = "git+https://github.com/penumbra-zone/penumbra.git?tag=v0.81.0#8df36a4247ae90acc8aecc48bfa37e55785f779f" dependencies = [ "anyhow", "ark-ff", @@ -2300,8 +2302,8 @@ dependencies = [ [[package]] name = "penumbra-distributions" -version = "0.80.5" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=5e8ea2b12777e5956db6ea5c620877e5d1aa2de5#5e8ea2b12777e5956db6ea5c620877e5d1aa2de5" +version = "0.81.0" +source = "git+https://github.com/penumbra-zone/penumbra.git?tag=v0.81.0#8df36a4247ae90acc8aecc48bfa37e55785f779f" dependencies = [ "anyhow", "async-trait", @@ -2316,8 +2318,8 @@ dependencies = [ [[package]] name = "penumbra-fee" -version = "0.80.5" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=5e8ea2b12777e5956db6ea5c620877e5d1aa2de5#5e8ea2b12777e5956db6ea5c620877e5d1aa2de5" +version = "0.81.0" +source = "git+https://github.com/penumbra-zone/penumbra.git?tag=v0.81.0#8df36a4247ae90acc8aecc48bfa37e55785f779f" dependencies = [ "anyhow", "ark-ff", @@ -2340,8 +2342,8 @@ dependencies = [ [[package]] name = "penumbra-governance" -version = "0.80.5" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=5e8ea2b12777e5956db6ea5c620877e5d1aa2de5#5e8ea2b12777e5956db6ea5c620877e5d1aa2de5" +version = "0.81.0" +source = "git+https://github.com/penumbra-zone/penumbra.git?tag=v0.81.0#8df36a4247ae90acc8aecc48bfa37e55785f779f" dependencies = [ "anyhow", "ark-ff", @@ -2389,8 +2391,8 @@ dependencies = [ [[package]] name = "penumbra-ibc" -version = "0.80.5" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=5e8ea2b12777e5956db6ea5c620877e5d1aa2de5#5e8ea2b12777e5956db6ea5c620877e5d1aa2de5" +version = "0.81.0" +source = "git+https://github.com/penumbra-zone/penumbra.git?tag=v0.81.0#8df36a4247ae90acc8aecc48bfa37e55785f779f" dependencies = [ "anyhow", "ark-ff", @@ -2424,8 +2426,8 @@ dependencies = [ [[package]] name = "penumbra-keys" -version = "0.80.5" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=5e8ea2b12777e5956db6ea5c620877e5d1aa2de5#5e8ea2b12777e5956db6ea5c620877e5d1aa2de5" +version = "0.81.0" +source = "git+https://github.com/penumbra-zone/penumbra.git?tag=v0.81.0#8df36a4247ae90acc8aecc48bfa37e55785f779f" dependencies = [ "aes", "anyhow", @@ -2468,8 +2470,8 @@ dependencies = [ [[package]] name = "penumbra-num" -version = "0.80.5" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=5e8ea2b12777e5956db6ea5c620877e5d1aa2de5#5e8ea2b12777e5956db6ea5c620877e5d1aa2de5" +version = "0.81.0" +source = "git+https://github.com/penumbra-zone/penumbra.git?tag=v0.81.0#8df36a4247ae90acc8aecc48bfa37e55785f779f" dependencies = [ "anyhow", "ark-ff", @@ -2504,8 +2506,8 @@ dependencies = [ [[package]] name = "penumbra-proof-params" -version = "0.80.5" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=5e8ea2b12777e5956db6ea5c620877e5d1aa2de5#5e8ea2b12777e5956db6ea5c620877e5d1aa2de5" +version = "0.81.0" +source = "git+https://github.com/penumbra-zone/penumbra.git?tag=v0.81.0#8df36a4247ae90acc8aecc48bfa37e55785f779f" dependencies = [ "anyhow", "ark-ec", @@ -2529,8 +2531,8 @@ dependencies = [ [[package]] name = "penumbra-proto" -version = "0.80.5" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=5e8ea2b12777e5956db6ea5c620877e5d1aa2de5#5e8ea2b12777e5956db6ea5c620877e5d1aa2de5" +version = "0.81.0" +source = "git+https://github.com/penumbra-zone/penumbra.git?tag=v0.81.0#8df36a4247ae90acc8aecc48bfa37e55785f779f" dependencies = [ "anyhow", "async-trait", @@ -2556,8 +2558,8 @@ dependencies = [ [[package]] name = "penumbra-sct" -version = "0.80.5" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=5e8ea2b12777e5956db6ea5c620877e5d1aa2de5#5e8ea2b12777e5956db6ea5c620877e5d1aa2de5" +version = "0.81.0" +source = "git+https://github.com/penumbra-zone/penumbra.git?tag=v0.81.0#8df36a4247ae90acc8aecc48bfa37e55785f779f" dependencies = [ "anyhow", "ark-ff", @@ -2589,8 +2591,8 @@ dependencies = [ [[package]] name = "penumbra-shielded-pool" -version = "0.80.5" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=5e8ea2b12777e5956db6ea5c620877e5d1aa2de5#5e8ea2b12777e5956db6ea5c620877e5d1aa2de5" +version = "0.81.0" +source = "git+https://github.com/penumbra-zone/penumbra.git?tag=v0.81.0#8df36a4247ae90acc8aecc48bfa37e55785f779f" dependencies = [ "anyhow", "ark-ff", @@ -2640,8 +2642,8 @@ dependencies = [ [[package]] name = "penumbra-stake" -version = "0.80.5" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=5e8ea2b12777e5956db6ea5c620877e5d1aa2de5#5e8ea2b12777e5956db6ea5c620877e5d1aa2de5" +version = "0.81.0" +source = "git+https://github.com/penumbra-zone/penumbra.git?tag=v0.81.0#8df36a4247ae90acc8aecc48bfa37e55785f779f" dependencies = [ "anyhow", "ark-ff", @@ -2681,8 +2683,8 @@ dependencies = [ [[package]] name = "penumbra-tct" -version = "0.80.5" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=5e8ea2b12777e5956db6ea5c620877e5d1aa2de5#5e8ea2b12777e5956db6ea5c620877e5d1aa2de5" +version = "0.81.0" +source = "git+https://github.com/penumbra-zone/penumbra.git?tag=v0.81.0#8df36a4247ae90acc8aecc48bfa37e55785f779f" dependencies = [ "ark-ed-on-bls12-377", "ark-ff", @@ -2694,6 +2696,7 @@ dependencies = [ "decaf377", "derivative", "futures", + "getrandom", "hash_hasher", "hex", "im", @@ -2709,8 +2712,8 @@ dependencies = [ [[package]] name = "penumbra-transaction" -version = "0.80.5" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=5e8ea2b12777e5956db6ea5c620877e5d1aa2de5#5e8ea2b12777e5956db6ea5c620877e5d1aa2de5" +version = "0.81.0" +source = "git+https://github.com/penumbra-zone/penumbra.git?tag=v0.81.0#8df36a4247ae90acc8aecc48bfa37e55785f779f" dependencies = [ "anyhow", "ark-ff", @@ -2760,8 +2763,8 @@ dependencies = [ [[package]] name = "penumbra-txhash" -version = "0.80.5" -source = "git+https://github.com/penumbra-zone/penumbra.git?rev=5e8ea2b12777e5956db6ea5c620877e5d1aa2de5#5e8ea2b12777e5956db6ea5c620877e5d1aa2de5" +version = "0.81.0" +source = "git+https://github.com/penumbra-zone/penumbra.git?tag=v0.81.0#8df36a4247ae90acc8aecc48bfa37e55785f779f" dependencies = [ "anyhow", "blake2b_simd 1.0.2", diff --git a/packages/wasm/crate/Cargo.toml b/packages/wasm/crate/Cargo.toml index aeca1c44b0..036d42adea 100644 --- a/packages/wasm/crate/Cargo.toml +++ b/packages/wasm/crate/Cargo.toml @@ -15,21 +15,21 @@ mock-database = [] [dependencies] # Update to tag dependency once https://github.com/penumbra-zone/penumbra/pull/4878 is in a release -penumbra-auction = { git = "https://github.com/penumbra-zone/penumbra.git", rev = "5e8ea2b12777e5956db6ea5c620877e5d1aa2de5", package = "penumbra-auction", default-features = false } -penumbra-asset = { git = "https://github.com/penumbra-zone/penumbra.git", rev = "5e8ea2b12777e5956db6ea5c620877e5d1aa2de5", package = "penumbra-asset" } -penumbra-compact-block = { git = "https://github.com/penumbra-zone/penumbra.git", rev = "5e8ea2b12777e5956db6ea5c620877e5d1aa2de5", package = "penumbra-compact-block", default-features = false } -penumbra-dex = { git = "https://github.com/penumbra-zone/penumbra.git", rev = "5e8ea2b12777e5956db6ea5c620877e5d1aa2de5", package = "penumbra-dex", default-features = false } -penumbra-fee = { git = "https://github.com/penumbra-zone/penumbra.git", rev = "5e8ea2b12777e5956db6ea5c620877e5d1aa2de5", package = "penumbra-fee", default-features = false } -penumbra-governance = { git = "https://github.com/penumbra-zone/penumbra.git", rev = "5e8ea2b12777e5956db6ea5c620877e5d1aa2de5", package = "penumbra-governance", default-features = false } -penumbra-keys = { git = "https://github.com/penumbra-zone/penumbra.git", rev = "5e8ea2b12777e5956db6ea5c620877e5d1aa2de5", package = "penumbra-keys" } -penumbra-num = { git = "https://github.com/penumbra-zone/penumbra.git", rev = "5e8ea2b12777e5956db6ea5c620877e5d1aa2de5", package = "penumbra-num" } -penumbra-proof-params = { git = "https://github.com/penumbra-zone/penumbra.git", rev = "5e8ea2b12777e5956db6ea5c620877e5d1aa2de5", package = "penumbra-proof-params", default-features = false } -penumbra-proto = { git = "https://github.com/penumbra-zone/penumbra.git", rev = "5e8ea2b12777e5956db6ea5c620877e5d1aa2de5", package = "penumbra-proto", default-features = false } -penumbra-sct = { git = "https://github.com/penumbra-zone/penumbra.git", rev = "5e8ea2b12777e5956db6ea5c620877e5d1aa2de5", package = "penumbra-sct", default-features = false } -penumbra-shielded-pool = { git = "https://github.com/penumbra-zone/penumbra.git", rev = "5e8ea2b12777e5956db6ea5c620877e5d1aa2de5", package = "penumbra-shielded-pool", default-features = false } -penumbra-stake = { git = "https://github.com/penumbra-zone/penumbra.git", rev = "5e8ea2b12777e5956db6ea5c620877e5d1aa2de5", package = "penumbra-stake", default-features = false } -penumbra-tct = { git = "https://github.com/penumbra-zone/penumbra.git", rev = "5e8ea2b12777e5956db6ea5c620877e5d1aa2de5", package = "penumbra-tct" } -penumbra-transaction = { git = "https://github.com/penumbra-zone/penumbra.git", rev = "5e8ea2b12777e5956db6ea5c620877e5d1aa2de5", package = "penumbra-transaction", default-features = false } +penumbra-auction = { git = "https://github.com/penumbra-zone/penumbra.git", tag = "v0.81.0", package = "penumbra-auction", default-features = false } +penumbra-asset = { git = "https://github.com/penumbra-zone/penumbra.git", tag = "v0.81.0", package = "penumbra-asset" } +penumbra-compact-block = { git = "https://github.com/penumbra-zone/penumbra.git", tag = "v0.81.0", package = "penumbra-compact-block", default-features = false } +penumbra-dex = { git = "https://github.com/penumbra-zone/penumbra.git", tag = "v0.81.0", package = "penumbra-dex", default-features = false } +penumbra-fee = { git = "https://github.com/penumbra-zone/penumbra.git", tag = "v0.81.0", package = "penumbra-fee", default-features = false } +penumbra-governance = { git = "https://github.com/penumbra-zone/penumbra.git", tag = "v0.81.0", package = "penumbra-governance", default-features = false } +penumbra-keys = { git = "https://github.com/penumbra-zone/penumbra.git", tag = "v0.81.0", package = "penumbra-keys" } +penumbra-num = { git = "https://github.com/penumbra-zone/penumbra.git", tag = "v0.81.0", package = "penumbra-num" } +penumbra-proof-params = { git = "https://github.com/penumbra-zone/penumbra.git", tag = "v0.81.0", package = "penumbra-proof-params", default-features = false } +penumbra-proto = { git = "https://github.com/penumbra-zone/penumbra.git", tag = "v0.81.0", package = "penumbra-proto", default-features = false } +penumbra-sct = { git = "https://github.com/penumbra-zone/penumbra.git", tag = "v0.81.0", package = "penumbra-sct", default-features = false } +penumbra-shielded-pool = { git = "https://github.com/penumbra-zone/penumbra.git", tag = "v0.81.0", package = "penumbra-shielded-pool", default-features = false } +penumbra-stake = { git = "https://github.com/penumbra-zone/penumbra.git", tag = "v0.81.0", package = "penumbra-stake", default-features = false } +penumbra-tct = { git = "https://github.com/penumbra-zone/penumbra.git", tag = "v0.81.0", package = "penumbra-tct" } +penumbra-transaction = { git = "https://github.com/penumbra-zone/penumbra.git", tag = "v0.81.0", package = "penumbra-transaction", default-features = false } anyhow = "1.0.89" ark-ff = { version = "0.4.2", features = ["std"] } diff --git a/packages/wasm/crate/src/keys.rs b/packages/wasm/crate/src/keys.rs index 1838ff75ca..22bcea5ef0 100644 --- a/packages/wasm/crate/src/keys.rs +++ b/packages/wasm/crate/src/keys.rs @@ -181,3 +181,24 @@ pub fn forwarding_addr_inner(sequence: u16, account: Option, fvk: &FullView address } + +#[wasm_bindgen(getter_with_clone)] +pub struct TransparentAddrResponse { + /// The raw (binary) transparent address + pub address: Vec, + /// The t-address encoding of the transparent address + pub encoding: String, +} + +/// Returns the "truncated" address (t-addr) associated with the account. +#[wasm_bindgen] +pub fn get_transparent_address(full_viewing_key: &[u8]) -> WasmResult { + let fvk: FullViewingKey = FullViewingKey::decode(full_viewing_key)?; + let encoding = fvk.incoming().transparent_address(); + let address: Address = encoding.parse().expect("encoding transparent address"); + + Ok(TransparentAddrResponse { + address: address.encode_to_vec(), + encoding: encoding.to_string(), + }) +} diff --git a/packages/wasm/crate/tests/test_metadata.rs b/packages/wasm/crate/tests/test_metadata.rs index d36aa8ce98..0eafec0a11 100644 --- a/packages/wasm/crate/tests/test_metadata.rs +++ b/packages/wasm/crate/tests/test_metadata.rs @@ -39,6 +39,7 @@ fn get_metadata_for(display_denom: &str, base_denom_is_display_denom: bool) -> p penumbra_asset_id: None, symbol: String::from(""), priority_score: 0, + badges: Vec::new(), } } diff --git a/packages/wasm/src/keys.ts b/packages/wasm/src/keys.ts index 24340e210f..ede3bed6be 100644 --- a/packages/wasm/src/keys.ts +++ b/packages/wasm/src/keys.ts @@ -4,6 +4,7 @@ import { get_ephemeral_address, get_full_viewing_key, get_noble_forwarding_addr, + get_transparent_address, get_wallet_id, } from '../wasm/index.js'; import { @@ -55,3 +56,12 @@ export const getNobleForwardingAddr = ( penumbraAddr: Address.fromBinary(res.penumbra_addr_bytes), }; }; + +// Generates a transparent address that ensures bech32m encoding compatibility. +export const getTransparentAddress = (fvk: FullViewingKey) => { + const res = get_transparent_address(fvk.toBinary()); + return { + address: Address.fromBinary(res.address), + encoding: res.encoding, + }; +}; From 899b1767a29d4bc0dff1a3c68efa6a16f5f1841a Mon Sep 17 00:00:00 2001 From: Tal Derei Date: Wed, 18 Dec 2024 11:31:07 -0800 Subject: [PATCH 02/19] backwards compatibility with existing frontends --- apps/minifront/src/state/ibc-out.ts | 28 +++++++++++++------ .../src/view-service/transparent-address.ts | 5 ---- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/apps/minifront/src/state/ibc-out.ts b/apps/minifront/src/state/ibc-out.ts index 0c7453ed17..e8aab4762f 100644 --- a/apps/minifront/src/state/ibc-out.ts +++ b/apps/minifront/src/state/ibc-out.ts @@ -25,7 +25,6 @@ import { Channel } from '@penumbra-zone/protobuf/ibc/core/channel/v1/channel_pb' import { BLOCKS_PER_HOUR } from './constants'; import { createZQuery, ZQueryState } from '@penumbra-zone/zquery'; import { getChains } from '../fetchers/registry'; -import { bech32ChainIds } from './shared'; import { penumbra } from '../penumbra'; import { IbcChannelService, @@ -33,7 +32,7 @@ import { IbcConnectionService, ViewService, } from '@penumbra-zone/protobuf'; -import { PartialMessage } from '@bufbuild/protobuf'; +import { bech32ChainIds } from './shared'; export const { chains, useChains } = createZQuery({ name: 'chains', @@ -208,7 +207,7 @@ const getPlanRequest = async ({ } const addressIndex = getAddressIndex(selection.accountAddress); - const { address: returnAddress } = await penumbra + let { address: returnAddress } = await penumbra .service(ViewService) .ephemeralAddress({ addressIndex }); if (!returnAddress) { @@ -225,9 +224,20 @@ const getPlanRequest = async ({ throw new Error('Error with generating IBC transparent address'); } - // Detect USDC Noble withdrawals, and use transparent (t-addr) addresses - // to ensure compatibility. Prepare the ICS20 withdrawal messages with the t-addr - // flag set to 'true' + // IBC-related fields + let denom = getMetadata(selection.balanceView).base; + let useTransparentAddress = false; + + // Temporary: detect USDC Noble withdrawals, and use transparent (t-addr) addresses + // to ensure bech32m encoding compatibility. + + if (denom.includes('uusdc') && chain.chainId == 'noble-1') { + // Use the t-addr for USDC withdrawals, and don't override existing + // 'useCompatAddress' field to maintain backwards compatibility. + useTransparentAddress = true; + // Set the return address to the t-addr. + returnAddress = t_addr; + } return new TransactionPlannerRequest({ ics20Withdrawals: [ @@ -236,14 +246,14 @@ const getPlanRequest = async ({ BigNumber(amount), getDisplayDenomExponentFromValueView(selection.balanceView), ), - denom: { denom: getMetadata(selection.balanceView).base }, + denom: { denom }, destinationChainAddress, returnAddress, timeoutHeight, timeoutTime, sourceChannel: chain.channelId, - useCompatAddress: false, - useTransparentAddress: true, // temporarily hardcoding for testing purposes + useCompatAddress: bech32ChainIds.includes(chain.chainId), + useTransparentAddress, }, ], source: addressIndex, diff --git a/packages/services/src/view-service/transparent-address.ts b/packages/services/src/view-service/transparent-address.ts index c91bb104eb..95cdce48b5 100644 --- a/packages/services/src/view-service/transparent-address.ts +++ b/packages/services/src/view-service/transparent-address.ts @@ -10,9 +10,4 @@ export const transparentAddress: Impl['transparentAddress'] = async (_, ctx) => address: t_addr.address, encoding: t_addr.encoding, }; - - // return new TransparentAddressResponse({ - // address: t_addr.address, - // encoding: t_addr.encoding, - // }); }; From 640fbd18d315f3eb634589525510c54e073e6f87 Mon Sep 17 00:00:00 2001 From: Tal Derei Date: Wed, 18 Dec 2024 12:02:38 -0800 Subject: [PATCH 03/19] changeset --- .changeset/wet-wombats-approve.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .changeset/wet-wombats-approve.md diff --git a/.changeset/wet-wombats-approve.md b/.changeset/wet-wombats-approve.md new file mode 100644 index 0000000000..a955a95676 --- /dev/null +++ b/.changeset/wet-wombats-approve.md @@ -0,0 +1,8 @@ +--- +'@penumbra-zone/protobuf': major +'@penumbra-zone/services': minor +'minifront': minor +'@penumbra-zone/wasm': minor +--- + +support transparent addresses for usdc noble IBC withdrawals" From 10ffb2ce0b8557188274d8acbbe499a0f1027ed5 Mon Sep 17 00:00:00 2001 From: Tal Derei Date: Thu, 19 Dec 2024 02:57:35 -0800 Subject: [PATCH 04/19] fix inbound / outbound ibc transfers --- apps/minifront/src/state/ibc-in/index.tsx | 25 ++++++++++++++++++++--- apps/minifront/src/state/ibc-out.ts | 5 ++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/apps/minifront/src/state/ibc-in/index.tsx b/apps/minifront/src/state/ibc-in/index.tsx index 23491f3b82..4483aff275 100644 --- a/apps/minifront/src/state/ibc-in/index.tsx +++ b/apps/minifront/src/state/ibc-in/index.tsx @@ -21,7 +21,8 @@ import { MsgTransfer } from 'cosmjs-types/ibc/applications/transfer/v1/tx'; import { parseRevisionNumberFromChainId } from './parse-revision-number-from-chain-id'; import { bech32ChainIds } from '../shared.ts'; import { penumbra } from '../../penumbra.ts'; -import { TendermintProxyService } from '@penumbra-zone/protobuf'; +import { TendermintProxyService, ViewService } from '@penumbra-zone/protobuf'; +import { TransparentAddressRequest } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb'; export interface IbcInSlice { selectedChain?: ChainInfo; @@ -198,7 +199,7 @@ async function execute( throw new Error('Penumbra chain id could not be retrieved'); } - const penumbraAddress = await getPenumbraAddress(account, selectedChain.chainId); + let penumbraAddress = await getPenumbraAddress(account, selectedChain.chainId); if (!penumbraAddress) { throw new Error('Penumbra address not available'); } @@ -207,11 +208,29 @@ async function execute( const assetMetadata = augmentToAsset(coin.raw.denom, selectedChain.chainName); const transferToken = fromDisplayAmount(assetMetadata, coin.displayDenom, amount); + + const { address: t_addr, encoding: encoding } = await penumbra + .service(ViewService) + .transparentAddress(new TransparentAddressRequest({})); + if (!t_addr) { + throw new Error('Error with generating IBC transparent address'); + } + + // Temporary: detect USDC Noble inbound transfers, and use transparent (t-addr) encoding + // to ensure bech32m encoding compatibility. + if ( + transferToken.denom.includes('uusdc') && + (selectedChain.chainId == 'noble-1' || selectedChain.chainId == 'grand-1') + ) { + // Set the reciever address to the t-addr encoding. + penumbraAddress = encoding; + } + const params: MsgTransfer = { sourcePort: 'transfer', sourceChannel: await getCounterpartyChannelId(selectedChain, penumbraChainId), sender, - receiver: penumbraAddress, + receiver: penumbraAddress!, token: transferToken, timeoutHeight, timeoutTimestamp, diff --git a/apps/minifront/src/state/ibc-out.ts b/apps/minifront/src/state/ibc-out.ts index e8aab4762f..3e27fb5b6a 100644 --- a/apps/minifront/src/state/ibc-out.ts +++ b/apps/minifront/src/state/ibc-out.ts @@ -228,10 +228,9 @@ const getPlanRequest = async ({ let denom = getMetadata(selection.balanceView).base; let useTransparentAddress = false; - // Temporary: detect USDC Noble withdrawals, and use transparent (t-addr) addresses + // Temporary: detect USDC Noble withdrawals, and use a transparent (t-addr) address // to ensure bech32m encoding compatibility. - - if (denom.includes('uusdc') && chain.chainId == 'noble-1') { + if (denom.includes('uusdc') && (chain.chainId == 'noble-1' || chain.chainId == 'grand-1')) { // Use the t-addr for USDC withdrawals, and don't override existing // 'useCompatAddress' field to maintain backwards compatibility. useTransparentAddress = true; From 564951e6ad1095069440f6d9928ae2eeceea60e9 Mon Sep 17 00:00:00 2001 From: Tal Derei Date: Thu, 19 Dec 2024 03:09:32 -0800 Subject: [PATCH 05/19] linting --- apps/minifront/src/state/ibc-in/index.tsx | 4 ++-- apps/minifront/src/state/ibc-out.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/minifront/src/state/ibc-in/index.tsx b/apps/minifront/src/state/ibc-in/index.tsx index 4483aff275..0b1fc5ac8b 100644 --- a/apps/minifront/src/state/ibc-in/index.tsx +++ b/apps/minifront/src/state/ibc-in/index.tsx @@ -220,7 +220,7 @@ async function execute( // to ensure bech32m encoding compatibility. if ( transferToken.denom.includes('uusdc') && - (selectedChain.chainId == 'noble-1' || selectedChain.chainId == 'grand-1') + (selectedChain.chainId === 'noble-1' || selectedChain.chainId === 'grand-1') ) { // Set the reciever address to the t-addr encoding. penumbraAddress = encoding; @@ -230,7 +230,7 @@ async function execute( sourcePort: 'transfer', sourceChannel: await getCounterpartyChannelId(selectedChain, penumbraChainId), sender, - receiver: penumbraAddress!, + receiver: penumbraAddress, token: transferToken, timeoutHeight, timeoutTimestamp, diff --git a/apps/minifront/src/state/ibc-out.ts b/apps/minifront/src/state/ibc-out.ts index 3e27fb5b6a..160c498d40 100644 --- a/apps/minifront/src/state/ibc-out.ts +++ b/apps/minifront/src/state/ibc-out.ts @@ -217,7 +217,7 @@ const getPlanRequest = async ({ const { timeoutHeight, timeoutTime } = await getTimeout(chain.channelId); // Request transparent address from view service - const { address: t_addr, encoding: _encoding } = await penumbra + const { address: t_addr } = await penumbra .service(ViewService) .transparentAddress(new TransparentAddressRequest({})); if (!t_addr) { @@ -225,12 +225,12 @@ const getPlanRequest = async ({ } // IBC-related fields - let denom = getMetadata(selection.balanceView).base; + const denom = getMetadata(selection.balanceView).base; let useTransparentAddress = false; // Temporary: detect USDC Noble withdrawals, and use a transparent (t-addr) address // to ensure bech32m encoding compatibility. - if (denom.includes('uusdc') && (chain.chainId == 'noble-1' || chain.chainId == 'grand-1')) { + if (denom.includes('uusdc') && (chain.chainId === 'noble-1' || chain.chainId === 'grand-1')) { // Use the t-addr for USDC withdrawals, and don't override existing // 'useCompatAddress' field to maintain backwards compatibility. useTransparentAddress = true; From 326c11a12565eca34cc9e37b8b457c59a4e77ba9 Mon Sep 17 00:00:00 2001 From: Tal Derei Date: Thu, 19 Dec 2024 12:49:44 -0800 Subject: [PATCH 06/19] remove deprecated useCompatAddress field --- apps/minifront/src/state/ibc-out.ts | 9 ++------- .../components/ui/tx/actions-views/isc20-withdrawal.tsx | 4 ---- packages/wasm/crate/tests/test_deserialize.rs | 1 - 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/apps/minifront/src/state/ibc-out.ts b/apps/minifront/src/state/ibc-out.ts index 160c498d40..5c90a1844c 100644 --- a/apps/minifront/src/state/ibc-out.ts +++ b/apps/minifront/src/state/ibc-out.ts @@ -32,7 +32,6 @@ import { IbcConnectionService, ViewService, } from '@penumbra-zone/protobuf'; -import { bech32ChainIds } from './shared'; export const { chains, useChains } = createZQuery({ name: 'chains', @@ -228,13 +227,10 @@ const getPlanRequest = async ({ const denom = getMetadata(selection.balanceView).base; let useTransparentAddress = false; - // Temporary: detect USDC Noble withdrawals, and use a transparent (t-addr) address - // to ensure bech32m encoding compatibility. + // Temporary: detect USDC Noble withdrawals, and use a transparent (t-addr) return + // address to ensure bech32m encoding compatibility. if (denom.includes('uusdc') && (chain.chainId === 'noble-1' || chain.chainId === 'grand-1')) { - // Use the t-addr for USDC withdrawals, and don't override existing - // 'useCompatAddress' field to maintain backwards compatibility. useTransparentAddress = true; - // Set the return address to the t-addr. returnAddress = t_addr; } @@ -251,7 +247,6 @@ const getPlanRequest = async ({ timeoutHeight, timeoutTime, sourceChannel: chain.channelId, - useCompatAddress: bech32ChainIds.includes(chain.chainId), useTransparentAddress, }, ], diff --git a/packages/ui-deprecated/components/ui/tx/actions-views/isc20-withdrawal.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/isc20-withdrawal.tsx index 8492fa70d5..65efa54ff2 100644 --- a/packages/ui-deprecated/components/ui/tx/actions-views/isc20-withdrawal.tsx +++ b/packages/ui-deprecated/components/ui/tx/actions-views/isc20-withdrawal.tsx @@ -41,10 +41,6 @@ export const Ics20WithdrawalComponent = ({ value }: { value: Ics20Withdrawal }) )} - - {value.useCompatAddress ? 'TRUE' : 'FALSE'} - - {value.timeoutHeight && ( <> diff --git a/packages/wasm/crate/tests/test_deserialize.rs b/packages/wasm/crate/tests/test_deserialize.rs index c9956cf824..307e8c1e19 100644 --- a/packages/wasm/crate/tests/test_deserialize.rs +++ b/packages/wasm/crate/tests/test_deserialize.rs @@ -21,7 +21,6 @@ fn height_properly_serializes_from_json() { }, "timeoutTime": "1701471437169", "sourceChannel": "channel-0", - "useCompatAddress": true } "#; From 9dba72851a2d43044dd029ad04bf6bb121333915 Mon Sep 17 00:00:00 2001 From: Tal Derei Date: Thu, 19 Dec 2024 13:17:00 -0800 Subject: [PATCH 07/19] fix wasm test --- packages/wasm/crate/tests/test_deserialize.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/wasm/crate/tests/test_deserialize.rs b/packages/wasm/crate/tests/test_deserialize.rs index 307e8c1e19..2ba9bc660a 100644 --- a/packages/wasm/crate/tests/test_deserialize.rs +++ b/packages/wasm/crate/tests/test_deserialize.rs @@ -21,6 +21,7 @@ fn height_properly_serializes_from_json() { }, "timeoutTime": "1701471437169", "sourceChannel": "channel-0", + "useTransparentAddress": false } "#; @@ -32,5 +33,4 @@ fn height_properly_serializes_from_json() { let domain_type: Ics20Withdrawal = withdrawal_proto.try_into().unwrap(); assert_eq!(domain_type.timeout_height.revision_number, 5u64); assert_eq!(domain_type.timeout_height.revision_height, 3928271u64); - assert!(domain_type.use_compat_address); } From d8236caa074ab15b29fbd0c43396e194b724c03a Mon Sep 17 00:00:00 2001 From: Tal Derei Date: Fri, 20 Dec 2024 15:00:30 -0800 Subject: [PATCH 08/19] use ephemeral address format for ibc-in --- apps/minifront/src/state/ibc-in/index.tsx | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/apps/minifront/src/state/ibc-in/index.tsx b/apps/minifront/src/state/ibc-in/index.tsx index 0b1fc5ac8b..5b95f7a0ee 100644 --- a/apps/minifront/src/state/ibc-in/index.tsx +++ b/apps/minifront/src/state/ibc-in/index.tsx @@ -6,8 +6,6 @@ import { getAddrByIndex } from '../../fetchers/address'; import { bech32mAddress } from '@penumbra-zone/bech32m/penumbra'; import { Toast } from '@penumbra-zone/ui-deprecated/lib/toast/toast'; import { shorten } from '@penumbra-zone/types/string'; -import { Address } from '@penumbra-zone/protobuf/penumbra/core/keys/v1/keys_pb'; -import { bech32CompatAddress } from '@penumbra-zone/bech32m/penumbracompat1'; import { calculateFee, GasPrice, SigningStargateClient } from '@cosmjs/stargate'; import { chains } from 'chain-registry'; import { getChainId } from '../../fetchers/chain-id'; @@ -19,7 +17,6 @@ import { currentTimePlusTwoDaysRounded } from '../ibc-out'; import { EncodeObject } from '@cosmjs/proto-signing'; import { MsgTransfer } from 'cosmjs-types/ibc/applications/transfer/v1/tx'; import { parseRevisionNumberFromChainId } from './parse-revision-number-from-chain-id'; -import { bech32ChainIds } from '../shared.ts'; import { penumbra } from '../../penumbra.ts'; import { TendermintProxyService, ViewService } from '@penumbra-zone/protobuf'; import { TransparentAddressRequest } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb'; @@ -136,10 +133,6 @@ const getExplorerPage = (txHash: string, chainId?: string) => { return txPage.replace('${txHash}', txHash); }; -const getCompatibleBech32 = (chainId: string, address: Address): string => { - return bech32ChainIds.includes(chainId) ? bech32CompatAddress(address) : bech32mAddress(address); -}; - export const getPenumbraAddress = async ( account: number, chainId?: string, @@ -148,7 +141,7 @@ export const getPenumbraAddress = async ( return undefined; } const receiverAddress = await getAddrByIndex(account, true); - return getCompatibleBech32(chainId, receiverAddress); + return bech32mAddress(receiverAddress); }; const estimateFee = async ({ From b854f69593d98cf0c14fa1e1cbb5042a767c6aa5 Mon Sep 17 00:00:00 2001 From: Tal Derei Date: Fri, 20 Dec 2024 15:05:38 -0800 Subject: [PATCH 09/19] bech32 shared helper --- apps/minifront/src/state/ibc-in/index.tsx | 6 ++---- apps/minifront/src/state/ibc-out.ts | 3 ++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/minifront/src/state/ibc-in/index.tsx b/apps/minifront/src/state/ibc-in/index.tsx index 5b95f7a0ee..194060ae34 100644 --- a/apps/minifront/src/state/ibc-in/index.tsx +++ b/apps/minifront/src/state/ibc-in/index.tsx @@ -20,6 +20,7 @@ import { parseRevisionNumberFromChainId } from './parse-revision-number-from-cha import { penumbra } from '../../penumbra.ts'; import { TendermintProxyService, ViewService } from '@penumbra-zone/protobuf'; import { TransparentAddressRequest } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb'; +import { bech32ChainIds } from '../shared.ts'; export interface IbcInSlice { selectedChain?: ChainInfo; @@ -211,10 +212,7 @@ async function execute( // Temporary: detect USDC Noble inbound transfers, and use transparent (t-addr) encoding // to ensure bech32m encoding compatibility. - if ( - transferToken.denom.includes('uusdc') && - (selectedChain.chainId === 'noble-1' || selectedChain.chainId === 'grand-1') - ) { + if (transferToken.denom.includes('uusdc') && bech32ChainIds.includes(selectedChain.chainId)) { // Set the reciever address to the t-addr encoding. penumbraAddress = encoding; } diff --git a/apps/minifront/src/state/ibc-out.ts b/apps/minifront/src/state/ibc-out.ts index 5c90a1844c..3eccad9c83 100644 --- a/apps/minifront/src/state/ibc-out.ts +++ b/apps/minifront/src/state/ibc-out.ts @@ -32,6 +32,7 @@ import { IbcConnectionService, ViewService, } from '@penumbra-zone/protobuf'; +import { bech32ChainIds } from './shared'; export const { chains, useChains } = createZQuery({ name: 'chains', @@ -229,7 +230,7 @@ const getPlanRequest = async ({ // Temporary: detect USDC Noble withdrawals, and use a transparent (t-addr) return // address to ensure bech32m encoding compatibility. - if (denom.includes('uusdc') && (chain.chainId === 'noble-1' || chain.chainId === 'grand-1')) { + if (denom.includes('uusdc') && bech32ChainIds.includes(chain.chainId)) { useTransparentAddress = true; returnAddress = t_addr; } From 1b6a45e6997cb6a0bed1dfe92b6595057c4cc500 Mon Sep 17 00:00:00 2001 From: Tal Derei Date: Fri, 20 Dec 2024 15:23:45 -0800 Subject: [PATCH 10/19] comment: bech32, rather thana bech32m --- apps/minifront/src/state/ibc-in/index.tsx | 4 ++-- apps/minifront/src/state/ibc-out.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/minifront/src/state/ibc-in/index.tsx b/apps/minifront/src/state/ibc-in/index.tsx index 194060ae34..b92ac2800e 100644 --- a/apps/minifront/src/state/ibc-in/index.tsx +++ b/apps/minifront/src/state/ibc-in/index.tsx @@ -210,8 +210,8 @@ async function execute( throw new Error('Error with generating IBC transparent address'); } - // Temporary: detect USDC Noble inbound transfers, and use transparent (t-addr) encoding - // to ensure bech32m encoding compatibility. + // Temporary: detect USDC Noble inbound transfers, and use a transparent (t-addr) encoding + // to ensure Bech32 encoding compatibility. if (transferToken.denom.includes('uusdc') && bech32ChainIds.includes(selectedChain.chainId)) { // Set the reciever address to the t-addr encoding. penumbraAddress = encoding; diff --git a/apps/minifront/src/state/ibc-out.ts b/apps/minifront/src/state/ibc-out.ts index 3eccad9c83..f60abce21d 100644 --- a/apps/minifront/src/state/ibc-out.ts +++ b/apps/minifront/src/state/ibc-out.ts @@ -229,7 +229,7 @@ const getPlanRequest = async ({ let useTransparentAddress = false; // Temporary: detect USDC Noble withdrawals, and use a transparent (t-addr) return - // address to ensure bech32m encoding compatibility. + // address to ensure Bech32 encoding compatibility. if (denom.includes('uusdc') && bech32ChainIds.includes(chain.chainId)) { useTransparentAddress = true; returnAddress = t_addr; From b6cd1facaf837d60b8e41b1354b5990e9cd1dc5e Mon Sep 17 00:00:00 2001 From: Tal Derei Date: Fri, 20 Dec 2024 16:22:24 -0800 Subject: [PATCH 11/19] timeout msg --- apps/minifront/src/state/ibc-out.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/minifront/src/state/ibc-out.ts b/apps/minifront/src/state/ibc-out.ts index f60abce21d..396ab4e5b5 100644 --- a/apps/minifront/src/state/ibc-out.ts +++ b/apps/minifront/src/state/ibc-out.ts @@ -231,6 +231,7 @@ const getPlanRequest = async ({ // Temporary: detect USDC Noble withdrawals, and use a transparent (t-addr) return // address to ensure Bech32 encoding compatibility. if (denom.includes('uusdc') && bech32ChainIds.includes(chain.chainId)) { + // Outbound IBC transfers timeout without setting either of these fields. useTransparentAddress = true; returnAddress = t_addr; } From 28054ef3afa6f2ada7881e0b503a31ac4b8636f6 Mon Sep 17 00:00:00 2001 From: Tal Derei Date: Sat, 21 Dec 2024 04:07:38 -0800 Subject: [PATCH 12/19] remove compat address format from bech32 and types package --- packages/bech32m/src/format/bytes.ts | 1 - packages/bech32m/src/format/index.ts | 6 ----- packages/bech32m/src/format/inner.ts | 1 - packages/bech32m/src/format/prefix.ts | 1 - packages/bech32m/src/format/strings.ts | 1 - packages/bech32m/src/penumbracompat1.ts | 24 ------------------ .../bech32m/src/test/penumbracompat1.test.ts | 25 ------------------- packages/types/src/address.test.ts | 8 ------ packages/types/src/address.ts | 4 --- 9 files changed, 71 deletions(-) delete mode 100644 packages/bech32m/src/penumbracompat1.ts delete mode 100644 packages/bech32m/src/test/penumbracompat1.test.ts diff --git a/packages/bech32m/src/format/bytes.ts b/packages/bech32m/src/format/bytes.ts index 0cc867116c..daee8ace22 100644 --- a/packages/bech32m/src/format/bytes.ts +++ b/packages/bech32m/src/format/bytes.ts @@ -4,7 +4,6 @@ export const ByteLength = { passet: 32, pauctid: 32, penumbra: 80, - penumbracompat1: 80, penumbrafullviewingkey: 64, penumbragovern: 32, penumbraspendkey: 32, diff --git a/packages/bech32m/src/format/index.ts b/packages/bech32m/src/format/index.ts index fff0b57a4a..87904c2995 100644 --- a/packages/bech32m/src/format/index.ts +++ b/packages/bech32m/src/format/index.ts @@ -31,12 +31,6 @@ export default { byteLength: ByteLength.penumbra, innerName: Inner.penumbra, }, - penumbracompat1: { - prefix: Prefixes.penumbracompat1, - stringLength: StringLength.penumbracompat1, - byteLength: ByteLength.penumbracompat1, - innerName: Inner.penumbracompat1, - }, penumbrafullviewingkey: { prefix: Prefixes.penumbrafullviewingkey, stringLength: StringLength.penumbrafullviewingkey, diff --git a/packages/bech32m/src/format/inner.ts b/packages/bech32m/src/format/inner.ts index 9e21eb9af5..d3c1141649 100644 --- a/packages/bech32m/src/format/inner.ts +++ b/packages/bech32m/src/format/inner.ts @@ -4,7 +4,6 @@ export const Inner = { passet: 'inner', pauctid: 'inner', penumbra: 'inner', - penumbracompat1: 'inner', penumbrafullviewingkey: 'inner', penumbragovern: 'gk', penumbraspendkey: 'inner', diff --git a/packages/bech32m/src/format/prefix.ts b/packages/bech32m/src/format/prefix.ts index bc89718fa7..0afbf525c2 100644 --- a/packages/bech32m/src/format/prefix.ts +++ b/packages/bech32m/src/format/prefix.ts @@ -2,7 +2,6 @@ export const Prefixes = { passet: 'passet', pauctid: 'pauctid', penumbra: 'penumbra', - penumbracompat1: 'penumbracompat1', penumbrafullviewingkey: 'penumbrafullviewingkey', penumbragovern: 'penumbragovern', penumbraspendkey: 'penumbraspendkey', diff --git a/packages/bech32m/src/format/strings.ts b/packages/bech32m/src/format/strings.ts index db047a78fd..5b35ba5d70 100644 --- a/packages/bech32m/src/format/strings.ts +++ b/packages/bech32m/src/format/strings.ts @@ -4,7 +4,6 @@ export const StringLength = { passet: 65, pauctid: 66, penumbra: 143, - penumbracompat1: 150, penumbrafullviewingkey: 132, penumbragovern: 73, penumbraspendkey: 75, diff --git a/packages/bech32m/src/penumbracompat1.ts b/packages/bech32m/src/penumbracompat1.ts deleted file mode 100644 index 8da7caec0b..0000000000 --- a/packages/bech32m/src/penumbracompat1.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { fromBech32, toBech32 } from './format/convert.js'; -import { Inner } from './format/inner.js'; -import { Prefixes } from './format/prefix.js'; - -const innerName = Inner.penumbracompat1; -const prefix = Prefixes.penumbracompat1; - -export const bech32CompatAddress = ({ [innerName]: bytes }: { [innerName]: Uint8Array }) => - toBech32(bytes, prefix); - -export const compatAddressFromBech32 = (penumbracompat1: string): { [innerName]: Uint8Array } => ({ - [innerName]: fromBech32(penumbracompat1 as `${typeof prefix}1${string}`, prefix), -}); - -export const isCompatAddress = (check: string): check is `${typeof prefix}1${string}` => { - try { - compatAddressFromBech32(check); - return true; - } catch { - return false; - } -}; - -export { PENUMBRA_BECH32M_ADDRESS_LENGTH, PENUMBRA_BECH32M_ADDRESS_PREFIX } from './index.js'; diff --git a/packages/bech32m/src/test/penumbracompat1.test.ts b/packages/bech32m/src/test/penumbracompat1.test.ts deleted file mode 100644 index d0422671b1..0000000000 --- a/packages/bech32m/src/test/penumbracompat1.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { describe } from 'vitest'; -import { generateTests } from './util/generate-tests.js'; -import { bech32CompatAddress, compatAddressFromBech32 } from '../penumbracompat1.js'; -import { Prefixes } from '../format/prefix.js'; -import { Inner } from '../format/inner.js'; - -describe('compat address conversion', () => { - const okInner = new Uint8Array([ - 175, 182, 158, 255, 239, 16, 245, 221, 208, 117, 160, 44, 235, 175, 198, 0, 6, 216, 6, 143, 192, - 155, 159, 103, 97, 103, 136, 5, 78, 209, 17, 200, 68, 220, 182, 45, 20, 246, 181, 16, 117, 182, - 46, 141, 74, 101, 196, 86, 185, 124, 206, 253, 195, 57, 224, 34, 210, 22, 123, 246, 136, 10, - 208, 159, 24, 235, 148, 153, 211, 7, 137, 198, 158, 226, 221, 22, 208, 152, 246, 247, - ]); - const okBech32 = - 'penumbracompat1147mfall0zr6am5r45qkwht7xqqrdsp50czde7empv7yq2nk3z8yyfh9k9520ddgswkmzar22vhz9dwtuem7uxw0qytfpv7lk3q9dp8ccaw2fn5c838rfackazmgf3ahhwqq0da'; - - generateTests( - Prefixes.penumbracompat1, - Inner.penumbracompat1, - okInner, - okBech32, - bech32CompatAddress, - compatAddressFromBech32, - ); -}); diff --git a/packages/types/src/address.test.ts b/packages/types/src/address.test.ts index 9751b2d541..371769a152 100644 --- a/packages/types/src/address.test.ts +++ b/packages/types/src/address.test.ts @@ -2,14 +2,6 @@ import { describe, expect, test } from 'vitest'; import { parseIntoAddr } from './address.js'; describe('parseIntoAddr', () => { - test('works with compat', () => { - expect(() => - parseIntoAddr( - 'penumbracompat1147mfall0zr6am5r45qkwht7xqqrdsp50czde7empv7yq2nk3z8yyfh9k9520ddgswkmzar22vhz9dwtuem7uxw0qytfpv7lk3q9dp8ccaw2fn5c838rfackazmgf3ahhwqq0da', - ), - ).not.toThrow(); - }); - test('works with normal addresses', () => { expect(() => parseIntoAddr( diff --git a/packages/types/src/address.ts b/packages/types/src/address.ts index 97f1182f6c..cbf3f78f2b 100644 --- a/packages/types/src/address.ts +++ b/packages/types/src/address.ts @@ -1,10 +1,6 @@ import { Address } from '@penumbra-zone/protobuf/penumbra/core/keys/v1/keys_pb'; import { addressFromBech32m } from '@penumbra-zone/bech32m/penumbra'; -import { compatAddressFromBech32, isCompatAddress } from '@penumbra-zone/bech32m/penumbracompat1'; export const parseIntoAddr = (addrStr: string): Address => { - if (isCompatAddress(addrStr)) { - return new Address(compatAddressFromBech32(addrStr)); - } return new Address(addressFromBech32m(addrStr)); }; From ef1f212371a32d5768a927c5211bbdf8a201da5a Mon Sep 17 00:00:00 2001 From: Tal Derei Date: Sat, 21 Dec 2024 04:14:49 -0800 Subject: [PATCH 13/19] use t-addr field in ics20 withdrawal component --- .../components/ui/tx/actions-views/isc20-withdrawal.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/ui-deprecated/components/ui/tx/actions-views/isc20-withdrawal.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/isc20-withdrawal.tsx index 65efa54ff2..3fc9f5af49 100644 --- a/packages/ui-deprecated/components/ui/tx/actions-views/isc20-withdrawal.tsx +++ b/packages/ui-deprecated/components/ui/tx/actions-views/isc20-withdrawal.tsx @@ -41,6 +41,10 @@ export const Ics20WithdrawalComponent = ({ value }: { value: Ics20Withdrawal }) )} + + {value.useTransparentAddress ? 'TRUE' : 'FALSE'} + + {value.timeoutHeight && ( <> From ec1c370eb77aa6ba3b68dc0258d7801830d93365 Mon Sep 17 00:00:00 2001 From: Tal Derei Date: Sat, 21 Dec 2024 04:16:54 -0800 Subject: [PATCH 14/19] update changeset --- .../{wet-wombats-approve.md => perfect-colts-change.md} | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) rename .changeset/{wet-wombats-approve.md => perfect-colts-change.md} (50%) diff --git a/.changeset/wet-wombats-approve.md b/.changeset/perfect-colts-change.md similarity index 50% rename from .changeset/wet-wombats-approve.md rename to .changeset/perfect-colts-change.md index a955a95676..f4536a9871 100644 --- a/.changeset/wet-wombats-approve.md +++ b/.changeset/perfect-colts-change.md @@ -1,8 +1,10 @@ --- '@penumbra-zone/protobuf': major '@penumbra-zone/services': minor +'@penumbra-zone/bech32m': minor 'minifront': minor +'@penumbra-zone/types': minor '@penumbra-zone/wasm': minor --- -support transparent addresses for usdc noble IBC withdrawals" +support transparent addresses for usdc noble IBC withdrawals From 486e9a8d98ec87964c72695fbe9233e6b6fa07a7 Mon Sep 17 00:00:00 2001 From: Tal Derei Date: Sat, 21 Dec 2024 22:37:30 -0800 Subject: [PATCH 15/19] add compat and t-addr bech32 encoding --- packages/bech32m/src/format/bytes.ts | 2 ++ packages/bech32m/src/format/index.ts | 12 +++++++++ packages/bech32m/src/format/inner.ts | 2 ++ packages/bech32m/src/format/prefix.ts | 2 ++ packages/bech32m/src/format/strings.ts | 2 ++ packages/bech32m/src/index.ts | 3 +++ packages/bech32m/src/penumbracompat1.ts | 24 +++++++++++++++++ .../bech32m/src/test/penumbracompat1.test.ts | 25 +++++++++++++++++ packages/bech32m/src/test/tpenumbra.test.ts | 22 +++++++++++++++ packages/bech32m/src/tpenumbra.ts | 27 +++++++++++++++++++ packages/types/src/address.test.ts | 8 ++++++ packages/types/src/address.ts | 4 +++ packages/wasm/crate/src/keys.rs | 13 +++++++++ packages/wasm/src/keys.ts | 6 +++++ 14 files changed, 152 insertions(+) create mode 100644 packages/bech32m/src/penumbracompat1.ts create mode 100644 packages/bech32m/src/test/penumbracompat1.test.ts create mode 100644 packages/bech32m/src/test/tpenumbra.test.ts create mode 100644 packages/bech32m/src/tpenumbra.ts diff --git a/packages/bech32m/src/format/bytes.ts b/packages/bech32m/src/format/bytes.ts index daee8ace22..a34ad42db3 100644 --- a/packages/bech32m/src/format/bytes.ts +++ b/packages/bech32m/src/format/bytes.ts @@ -4,10 +4,12 @@ export const ByteLength = { passet: 32, pauctid: 32, penumbra: 80, + penumbracompat1: 80, penumbrafullviewingkey: 64, penumbragovern: 32, penumbraspendkey: 32, penumbravalid: 32, penumbrawalletid: 32, plpid: 32, + tpenumbra: 32, } as const satisfies Required>; diff --git a/packages/bech32m/src/format/index.ts b/packages/bech32m/src/format/index.ts index 87904c2995..e123e296e4 100644 --- a/packages/bech32m/src/format/index.ts +++ b/packages/bech32m/src/format/index.ts @@ -67,4 +67,16 @@ export default { byteLength: ByteLength.plpid, innerName: Inner.plpid, }, + penumbracompat1: { + prefix: Prefixes.penumbracompat1, + stringLength: StringLength.penumbracompat1, + byteLength: ByteLength.penumbracompat1, + innerName: Inner.penumbracompat1, + }, + tpenumbra: { + prefix: Prefixes.tpenumbra, + stringLength: StringLength.tpenumbra, + byteLength: ByteLength.tpenumbra, + innerName: Inner.tpenumbra, + }, } as const satisfies PenumbraBech32mSpec; diff --git a/packages/bech32m/src/format/inner.ts b/packages/bech32m/src/format/inner.ts index d3c1141649..f1ce08fd1e 100644 --- a/packages/bech32m/src/format/inner.ts +++ b/packages/bech32m/src/format/inner.ts @@ -10,4 +10,6 @@ export const Inner = { penumbravalid: 'ik', penumbrawalletid: 'inner', plpid: 'inner', + penumbracompat1: 'inner', + tpenumbra: 'inner', } as const satisfies Required>; diff --git a/packages/bech32m/src/format/prefix.ts b/packages/bech32m/src/format/prefix.ts index 0afbf525c2..1d11343e1b 100644 --- a/packages/bech32m/src/format/prefix.ts +++ b/packages/bech32m/src/format/prefix.ts @@ -8,6 +8,8 @@ export const Prefixes = { penumbravalid: 'penumbravalid', penumbrawalletid: 'penumbrawalletid', plpid: 'plpid', + penumbracompat1: 'penumbracompat1', + tpenumbra: 'tpenumbra', } as const; export type Prefix = keyof typeof Prefixes; diff --git a/packages/bech32m/src/format/strings.ts b/packages/bech32m/src/format/strings.ts index 5b35ba5d70..2d9d62e133 100644 --- a/packages/bech32m/src/format/strings.ts +++ b/packages/bech32m/src/format/strings.ts @@ -10,4 +10,6 @@ export const StringLength = { penumbravalid: 72, penumbrawalletid: 75, plpid: 64, + penumbracompat1: 150, + tpenumbra: 68, } as const satisfies Required>; diff --git a/packages/bech32m/src/index.ts b/packages/bech32m/src/index.ts index c1e32bca90..aa67955f4c 100644 --- a/packages/bech32m/src/index.ts +++ b/packages/bech32m/src/index.ts @@ -28,3 +28,6 @@ export const PENUMBRA_BECH32M_WALLETID_PREFIX = SPEC.penumbrawalletid.prefix; export const PENUMBRA_BECH32M_POSITIONID_LENGTH = SPEC.plpid.stringLength; export const PENUMBRA_BECH32M_POSITIONID_PREFIX = SPEC.plpid.prefix; + +export const PENUMBRA_BECH32M_TRANSPARENT_LENGTH = SPEC.tpenumbra.stringLength; +export const PENUMBRA_BECH32M_TRANSPARENT_PREFIX = SPEC.tpenumbra.prefix; diff --git a/packages/bech32m/src/penumbracompat1.ts b/packages/bech32m/src/penumbracompat1.ts new file mode 100644 index 0000000000..8da7caec0b --- /dev/null +++ b/packages/bech32m/src/penumbracompat1.ts @@ -0,0 +1,24 @@ +import { fromBech32, toBech32 } from './format/convert.js'; +import { Inner } from './format/inner.js'; +import { Prefixes } from './format/prefix.js'; + +const innerName = Inner.penumbracompat1; +const prefix = Prefixes.penumbracompat1; + +export const bech32CompatAddress = ({ [innerName]: bytes }: { [innerName]: Uint8Array }) => + toBech32(bytes, prefix); + +export const compatAddressFromBech32 = (penumbracompat1: string): { [innerName]: Uint8Array } => ({ + [innerName]: fromBech32(penumbracompat1 as `${typeof prefix}1${string}`, prefix), +}); + +export const isCompatAddress = (check: string): check is `${typeof prefix}1${string}` => { + try { + compatAddressFromBech32(check); + return true; + } catch { + return false; + } +}; + +export { PENUMBRA_BECH32M_ADDRESS_LENGTH, PENUMBRA_BECH32M_ADDRESS_PREFIX } from './index.js'; diff --git a/packages/bech32m/src/test/penumbracompat1.test.ts b/packages/bech32m/src/test/penumbracompat1.test.ts new file mode 100644 index 0000000000..d0422671b1 --- /dev/null +++ b/packages/bech32m/src/test/penumbracompat1.test.ts @@ -0,0 +1,25 @@ +import { describe } from 'vitest'; +import { generateTests } from './util/generate-tests.js'; +import { bech32CompatAddress, compatAddressFromBech32 } from '../penumbracompat1.js'; +import { Prefixes } from '../format/prefix.js'; +import { Inner } from '../format/inner.js'; + +describe('compat address conversion', () => { + const okInner = new Uint8Array([ + 175, 182, 158, 255, 239, 16, 245, 221, 208, 117, 160, 44, 235, 175, 198, 0, 6, 216, 6, 143, 192, + 155, 159, 103, 97, 103, 136, 5, 78, 209, 17, 200, 68, 220, 182, 45, 20, 246, 181, 16, 117, 182, + 46, 141, 74, 101, 196, 86, 185, 124, 206, 253, 195, 57, 224, 34, 210, 22, 123, 246, 136, 10, + 208, 159, 24, 235, 148, 153, 211, 7, 137, 198, 158, 226, 221, 22, 208, 152, 246, 247, + ]); + const okBech32 = + 'penumbracompat1147mfall0zr6am5r45qkwht7xqqrdsp50czde7empv7yq2nk3z8yyfh9k9520ddgswkmzar22vhz9dwtuem7uxw0qytfpv7lk3q9dp8ccaw2fn5c838rfackazmgf3ahhwqq0da'; + + generateTests( + Prefixes.penumbracompat1, + Inner.penumbracompat1, + okInner, + okBech32, + bech32CompatAddress, + compatAddressFromBech32, + ); +}); diff --git a/packages/bech32m/src/test/tpenumbra.test.ts b/packages/bech32m/src/test/tpenumbra.test.ts new file mode 100644 index 0000000000..889cb419cc --- /dev/null +++ b/packages/bech32m/src/test/tpenumbra.test.ts @@ -0,0 +1,22 @@ +import { describe } from 'vitest'; +import { generateTests } from './util/generate-tests.js'; +import { bech32TransparentAddress, transparentAddressFromBech32 } from '../tpenumbra.js'; +import { Prefixes } from '../format/prefix.js'; +import { Inner } from '../format/inner.js'; + +describe('transparent address conversion', () => { + const okInner = new Uint8Array([ + 102, 236, 169, 166, 203, 152, 194, 89, 236, 246, 59, 69, 221, 32, 49, 49, 83, 29, 119, 117, 124, + 201, 194, 156, 219, 251, 137, 202, 157, 235, 1, 15, + ]); + const okBech32 = 'tpenumbra1vmk2nfktnrp9nm8k8dza6gp3x9f36am40nyu98xmlwyu480tqy8sr3jfzd'; + + generateTests( + Prefixes.tpenumbra, + Inner.tpenumbra, + okInner, + okBech32, + bech32TransparentAddress, + transparentAddressFromBech32, + ); +}); diff --git a/packages/bech32m/src/tpenumbra.ts b/packages/bech32m/src/tpenumbra.ts new file mode 100644 index 0000000000..eaf60d5e33 --- /dev/null +++ b/packages/bech32m/src/tpenumbra.ts @@ -0,0 +1,27 @@ +import { fromBech32, toBech32 } from './format/convert.js'; +import { Inner } from './format/inner.js'; +import { Prefixes } from './format/prefix.js'; + +const innerName = Inner.tpenumbra; +const prefix = Prefixes.tpenumbra; + +export const bech32TransparentAddress = ({ [innerName]: bytes }: { [innerName]: Uint8Array }) => + toBech32(bytes, prefix); + +export const transparentAddressFromBech32 = (penumbra1: string): { [innerName]: Uint8Array } => ({ + [innerName]: fromBech32(penumbra1 as `${typeof prefix}1${string}`, prefix), +}); + +export const isAddress = (check: string): check is `${typeof prefix}1${string}` => { + try { + transparentAddressFromBech32(check); + return true; + } catch { + return false; + } +}; + +export { + PENUMBRA_BECH32M_TRANSPARENT_LENGTH, + PENUMBRA_BECH32M_TRANSPARENT_PREFIX, +} from './index.js'; diff --git a/packages/types/src/address.test.ts b/packages/types/src/address.test.ts index 371769a152..9751b2d541 100644 --- a/packages/types/src/address.test.ts +++ b/packages/types/src/address.test.ts @@ -2,6 +2,14 @@ import { describe, expect, test } from 'vitest'; import { parseIntoAddr } from './address.js'; describe('parseIntoAddr', () => { + test('works with compat', () => { + expect(() => + parseIntoAddr( + 'penumbracompat1147mfall0zr6am5r45qkwht7xqqrdsp50czde7empv7yq2nk3z8yyfh9k9520ddgswkmzar22vhz9dwtuem7uxw0qytfpv7lk3q9dp8ccaw2fn5c838rfackazmgf3ahhwqq0da', + ), + ).not.toThrow(); + }); + test('works with normal addresses', () => { expect(() => parseIntoAddr( diff --git a/packages/types/src/address.ts b/packages/types/src/address.ts index cbf3f78f2b..97f1182f6c 100644 --- a/packages/types/src/address.ts +++ b/packages/types/src/address.ts @@ -1,6 +1,10 @@ import { Address } from '@penumbra-zone/protobuf/penumbra/core/keys/v1/keys_pb'; import { addressFromBech32m } from '@penumbra-zone/bech32m/penumbra'; +import { compatAddressFromBech32, isCompatAddress } from '@penumbra-zone/bech32m/penumbracompat1'; export const parseIntoAddr = (addrStr: string): Address => { + if (isCompatAddress(addrStr)) { + return new Address(compatAddressFromBech32(addrStr)); + } return new Address(addressFromBech32m(addrStr)); }; diff --git a/packages/wasm/crate/src/keys.rs b/packages/wasm/crate/src/keys.rs index 22bcea5ef0..a6df15a413 100644 --- a/packages/wasm/crate/src/keys.rs +++ b/packages/wasm/crate/src/keys.rs @@ -202,3 +202,16 @@ pub fn get_transparent_address(full_viewing_key: &[u8]) -> WasmResult WasmResult> { + utils::set_panic_hook(); + + let address: Address = Address::decode(address)?; + let transmission_key = address.transmission_key(); + Ok(transmission_key.0.to_vec()) +} diff --git a/packages/wasm/src/keys.ts b/packages/wasm/src/keys.ts index ede3bed6be..d7d26dec52 100644 --- a/packages/wasm/src/keys.ts +++ b/packages/wasm/src/keys.ts @@ -5,6 +5,7 @@ import { get_full_viewing_key, get_noble_forwarding_addr, get_transparent_address, + get_transmission_key_by_address, get_wallet_id, } from '../wasm/index.js'; import { @@ -65,3 +66,8 @@ export const getTransparentAddress = (fvk: FullViewingKey) => { encoding: res.encoding, }; }; + +export const getTransmissionKeyByAddress = (address: Address) => { + const transmission_key = get_transmission_key_by_address(address.toBinary()); + return transmission_key; +}; From 472a542c8bac1d18cfc171e5cdcde858ac84a726 Mon Sep 17 00:00:00 2001 From: Tal Derei Date: Sun, 22 Dec 2024 00:29:22 -0800 Subject: [PATCH 16/19] preprocessing the transaction view --- .../view-service/transaction-info-by-hash.ts | 7 ++++- .../src/view-service/util/transaction-view.ts | 28 +++++++++++++++++++ .../ui/tx/actions-views/isc20-withdrawal.tsx | 5 +++- 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 packages/services/src/view-service/util/transaction-view.ts diff --git a/packages/services/src/view-service/transaction-info-by-hash.ts b/packages/services/src/view-service/transaction-info-by-hash.ts index b86ee41532..81b724f300 100644 --- a/packages/services/src/view-service/transaction-info-by-hash.ts +++ b/packages/services/src/view-service/transaction-info-by-hash.ts @@ -4,6 +4,7 @@ import { Code, ConnectError } from '@connectrpc/connect'; import { generateTransactionInfo } from '@penumbra-zone/wasm/transaction'; import { TransactionInfo } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb'; import { fvkCtx } from '../ctx/full-viewing-key.js'; +import { txvTranslator } from './util/transaction-view.js'; export const transactionInfoByHash: Impl['transactionInfoByHash'] = async (req, ctx) => { if (!req.id) { @@ -23,11 +24,15 @@ export const transactionInfoByHash: Impl['transactionInfoByHash'] = async (req, throw new ConnectError('Transaction not available', Code.NotFound); } - const { txp: perspective, txv: view } = await generateTransactionInfo( + let { txp: perspective, txv: view } = await generateTransactionInfo( await fvk(), transaction, indexedDb.constants(), ); + + // Invoke a higher-level translator on the transaction view. + view = await txvTranslator(view); + const txInfo = new TransactionInfo({ height, id: req.id, transaction, perspective, view }); return { txInfo }; }; diff --git a/packages/services/src/view-service/util/transaction-view.ts b/packages/services/src/view-service/util/transaction-view.ts new file mode 100644 index 0000000000..ac9f3ee760 --- /dev/null +++ b/packages/services/src/view-service/util/transaction-view.ts @@ -0,0 +1,28 @@ +import { TransactionView } from '@penumbra-zone/protobuf/penumbra/core/transaction/v1/transaction_pb'; +import { getTransmissionKeyByAddress } from '@penumbra-zone/wasm/keys'; + +// Some transaction views (TXVs) require additional preprocessing before being rendered +// in the UI component library. For example, when handling IBC withdrawals with transparent +// addresses, this component transforms ephemeral addresses into their bech32-encoded +// transparent form to ensure the proper data is being displayed. +export const txvTranslator = async (view: TransactionView): Promise => { + // 'Ics20Withdrawal' action view + const withdrawalAction = view?.bodyView?.actionViews?.find( + action => action.actionView.case === 'ics20Withdrawal', + ); + + if (withdrawalAction?.actionView.case === 'ics20Withdrawal') { + const withdrawal = withdrawalAction.actionView.value; + // Create 80-byte array initialized to zeros, then set first 32 bytes to transmission key. + // This constructs a valid address format where: + // - First 32 bytes: transmission key + // - Remaining 48 bytes: zeroed (16-byte diversifier + 32-byte clue key) + if (withdrawal.returnAddress && withdrawal.useTransparentAddress) { + const newInner = new Uint8Array(80).fill(0); + newInner.set(getTransmissionKeyByAddress(withdrawal.returnAddress), 0); + withdrawal.returnAddress.inner = newInner; + } + } + + return view; +}; diff --git a/packages/ui-deprecated/components/ui/tx/actions-views/isc20-withdrawal.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/isc20-withdrawal.tsx index 3fc9f5af49..8b649963d5 100644 --- a/packages/ui-deprecated/components/ui/tx/actions-views/isc20-withdrawal.tsx +++ b/packages/ui-deprecated/components/ui/tx/actions-views/isc20-withdrawal.tsx @@ -3,6 +3,7 @@ import { ViewBox } from '../viewbox'; import { ActionDetails } from './action-details'; import { joinLoHiAmount } from '@penumbra-zone/types/amount'; import { bech32mAddress } from '@penumbra-zone/bech32m/penumbra'; +import { bech32TransparentAddress } from '@penumbra-zone/bech32m/tpenumbra'; // Converts nanoseconds timestamp to UTC timestamp string export const getUtcTime = (time: bigint) => { @@ -37,7 +38,9 @@ export const Ics20WithdrawalComponent = ({ value }: { value: Ics20Withdrawal }) {value.returnAddress && ( - {bech32mAddress(value.returnAddress)} + {value.useTransparentAddress + ? bech32TransparentAddress({ inner: value.returnAddress.inner.slice(0, 32) }) + : bech32mAddress(value.returnAddress)} )} From a6549385859dbafcbfa15ec5c055577450e8a9c2 Mon Sep 17 00:00:00 2001 From: Tal Derei Date: Sun, 22 Dec 2024 00:45:14 -0800 Subject: [PATCH 17/19] linting --- .../services/src/view-service/transaction-info-by-hash.ts | 3 ++- packages/services/src/view-service/util/transaction-view.ts | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/services/src/view-service/transaction-info-by-hash.ts b/packages/services/src/view-service/transaction-info-by-hash.ts index 81b724f300..d81866a200 100644 --- a/packages/services/src/view-service/transaction-info-by-hash.ts +++ b/packages/services/src/view-service/transaction-info-by-hash.ts @@ -24,13 +24,14 @@ export const transactionInfoByHash: Impl['transactionInfoByHash'] = async (req, throw new ConnectError('Transaction not available', Code.NotFound); } - let { txp: perspective, txv: view } = await generateTransactionInfo( + const { txp: perspective, txv } = await generateTransactionInfo( await fvk(), transaction, indexedDb.constants(), ); // Invoke a higher-level translator on the transaction view. + let view = txv; view = await txvTranslator(view); const txInfo = new TransactionInfo({ height, id: req.id, transaction, perspective, view }); diff --git a/packages/services/src/view-service/util/transaction-view.ts b/packages/services/src/view-service/util/transaction-view.ts index ac9f3ee760..412aa57e02 100644 --- a/packages/services/src/view-service/util/transaction-view.ts +++ b/packages/services/src/view-service/util/transaction-view.ts @@ -5,9 +5,11 @@ import { getTransmissionKeyByAddress } from '@penumbra-zone/wasm/keys'; // in the UI component library. For example, when handling IBC withdrawals with transparent // addresses, this component transforms ephemeral addresses into their bech32-encoded // transparent form to ensure the proper data is being displayed. -export const txvTranslator = async (view: TransactionView): Promise => { +export const txvTranslator = (view: TransactionView): TransactionView => { // 'Ics20Withdrawal' action view - const withdrawalAction = view?.bodyView?.actionViews?.find( + if (!view.bodyView) return view; + + const withdrawalAction = view.bodyView.actionViews.find( action => action.actionView.case === 'ics20Withdrawal', ); From 2e58a1533d19e1c16dcb9ae2e3c5f916ae3df4ab Mon Sep 17 00:00:00 2001 From: Tal Derei Date: Sun, 22 Dec 2024 01:06:05 -0800 Subject: [PATCH 18/19] appease linter --- packages/services/src/view-service/transaction-info-by-hash.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/services/src/view-service/transaction-info-by-hash.ts b/packages/services/src/view-service/transaction-info-by-hash.ts index d81866a200..f0f63adaaf 100644 --- a/packages/services/src/view-service/transaction-info-by-hash.ts +++ b/packages/services/src/view-service/transaction-info-by-hash.ts @@ -31,8 +31,7 @@ export const transactionInfoByHash: Impl['transactionInfoByHash'] = async (req, ); // Invoke a higher-level translator on the transaction view. - let view = txv; - view = await txvTranslator(view); + const view = txvTranslator(txv); const txInfo = new TransactionInfo({ height, id: req.id, transaction, perspective, view }); return { txInfo }; From 871234303d0b6c48c196d2acfda185393a04e0ea Mon Sep 17 00:00:00 2001 From: Tal Derei Date: Sun, 22 Dec 2024 01:16:04 -0800 Subject: [PATCH 19/19] linting rule --- packages/services/src/view-service/util/transaction-view.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/services/src/view-service/util/transaction-view.ts b/packages/services/src/view-service/util/transaction-view.ts index 412aa57e02..7d0676a38a 100644 --- a/packages/services/src/view-service/util/transaction-view.ts +++ b/packages/services/src/view-service/util/transaction-view.ts @@ -7,7 +7,9 @@ import { getTransmissionKeyByAddress } from '@penumbra-zone/wasm/keys'; // transparent form to ensure the proper data is being displayed. export const txvTranslator = (view: TransactionView): TransactionView => { // 'Ics20Withdrawal' action view - if (!view.bodyView) return view; + if (!view.bodyView) { + return view; + } const withdrawalAction = view.bodyView.actionViews.find( action => action.actionView.case === 'ics20Withdrawal',