Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WalletConnect/BNB]: Add support for WalletConnect signing requests #3632

Merged
merged 18 commits into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/codegen-v2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ on:
jobs:
test:
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.trustwallet.core.app.blockchains.binance

import com.google.protobuf.ByteString
import com.trustwallet.core.app.utils.toHexBytes
import org.junit.Assert.assertEquals
import org.junit.Test
import wallet.core.jni.proto.Binance.SigningOutput
import wallet.core.jni.proto.WalletConnect
import wallet.core.jni.*
import wallet.core.jni.CoinType.BINANCE
import wallet.core.java.AnySigner
import wallet.core.jni.proto.Common

class TestBinanceWalletConnectSigning {
init {
System.loadLibrary("TrustWalletCore")
}

@Test
fun testSignBinanceTransactionFromWalletConnectRequest() {
// Step 1: Parse a signing request received through WalletConnect.

val parsingInput = WalletConnect.ParseRequestInput.newBuilder().apply {
method = WalletConnect.Method.CosmosSignAmino
payload = "{\"signerAddress\":\"bnb1grpf0955h0ykzq3ar5nmum7y6gdfl6lxfn46h2\",\"signDoc\":{\"account_number\":\"19\",\"chain_id\":\"chain-bnb\",\"memo\":\"\",\"data\":null,\"msgs\":[{\"inputs\":[{\"address\":\"bnb1grpf0955h0ykzq3ar5nmum7y6gdfl6lxfn46h2\",\"coins\":[{\"amount\":1001000000,\"denom\":\"BNB\"}]}],\"outputs\":[{\"address\":\"bnb13zeh6hs97d5eu2s5qerguhv8ewwue6u4ywa6yf\",\"coins\":[{\"amount\":1001000000,\"denom\":\"BNB\"}]}]}],\"sequence\":\"23\",\"source\":\"1\"}}"
}.build()

val parsingOutputBytes = WalletConnectRequest.parse(BINANCE, parsingInput.toByteArray())
val parsingOutput = WalletConnect.ParseRequestOutput.parseFrom(parsingOutputBytes)

assertEquals(parsingOutput.error, Common.SigningError.OK)

// Step 2: Set missing fields.

val signingInput = parsingOutput.binance.toBuilder().apply {
privateKey = ByteString.copyFrom("95949f757db1f57ca94a5dff23314accbe7abee89597bf6a3c7382c84d7eb832".toHexBytes())
}.build()

// Step 3: Sign the transaction.

val output = AnySigner.sign(signingInput, BINANCE, SigningOutput.parser())

assertEquals(output.error, Common.SigningError.OK)
assertEquals(output.signatureJson, "{\"pub_key\":{\"type\":\"tendermint/PubKeySecp256k1\",\"value\":\"Amo1kgCI2Yw4iMpoxT38k/RWRgJgbLuH8P5e5TPbOOUC\"},\"signature\":\"PCTHhMa7+Z1U/6uxU+3LbTxKd0k231xypdMolyVvjgYvMg+0dTMC+wqW8IxHWXTSDt/Ronu+7ac1h/WN3JWJdQ==\"}")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use tw_coin_entry::error::AddressResult;
use tw_coin_entry::modules::json_signer::NoJsonSigner;
use tw_coin_entry::modules::message_signer::NoMessageSigner;
use tw_coin_entry::modules::plan_builder::NoPlanBuilder;
use tw_coin_entry::modules::wallet_connector::NoWalletConnector;
use tw_coin_entry::prefix::NoPrefix;
use tw_keypair::tw::PublicKey;
use tw_proto::{BLOCKCHAIN}::Proto;
Expand All @@ -33,6 +34,7 @@ impl CoinEntry for {BLOCKCHAIN}Entry {
type JsonSigner = NoJsonSigner;
type PlanBuilder = NoPlanBuilder;
type MessageSigner = NoMessageSigner;
type WalletConnector = NoWalletConnector;

#[inline]
fn parse_address(
Expand Down
2 changes: 1 addition & 1 deletion codegen-v2/src/tests/samples/class.output.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2017-2023 Trust Wallet.
// Copyright © 2017-2024 Trust Wallet.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
Expand Down
2 changes: 1 addition & 1 deletion codegen-v2/src/tests/samples/enum.output.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2017-2023 Trust Wallet.
// Copyright © 2017-2024 Trust Wallet.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
Expand Down
2 changes: 1 addition & 1 deletion codegen-v2/src/tests/samples/enum_extension.output.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2017-2023 Trust Wallet.
// Copyright © 2017-2024 Trust Wallet.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
Expand Down
2 changes: 1 addition & 1 deletion codegen-v2/src/tests/samples/enum_private.output.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2017-2023 Trust Wallet.
// Copyright © 2017-2024 Trust Wallet.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
Expand Down
2 changes: 1 addition & 1 deletion codegen-v2/src/tests/samples/non-associated.output.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2017-2023 Trust Wallet.
// Copyright © 2017-2024 Trust Wallet.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
Expand Down
2 changes: 1 addition & 1 deletion codegen-v2/src/tests/samples/optional.output.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2017-2023 Trust Wallet.
// Copyright © 2017-2024 Trust Wallet.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
Expand Down
2 changes: 1 addition & 1 deletion codegen-v2/src/tests/samples/private_class.output.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2017-2023 Trust Wallet.
// Copyright © 2017-2024 Trust Wallet.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
Expand Down
2 changes: 1 addition & 1 deletion codegen-v2/src/tests/samples/struct.output.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2017-2023 Trust Wallet.
// Copyright © 2017-2024 Trust Wallet.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
Expand Down
27 changes: 27 additions & 0 deletions include/TrustWalletCore/TWWalletConnectRequest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright © 2017-2024 Trust Wallet.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
// file LICENSE at the root of the source code distribution tree.

#pragma once

#include "TWBase.h"
#include "TWCoinType.h"
#include "TWData.h"

TW_EXTERN_C_BEGIN

/// Represents a WalletConnect signing request.
TW_EXPORT_CLASS
struct TWWalletConnectRequest;

/// Parses the WalletConnect signing request as a `SigningInput`.
///
/// \param coin The given coin type to plan the transaction for.
/// \param input The serialized data of a `WalletConnect::Proto::ParseRequestInput` proto object.
/// \return The serialized data of `WalletConnect::Proto::ParseRequestOutput` proto object.
TW_EXPORT_STATIC_METHOD
TWData* _Nonnull TWWalletConnectRequestParse(enum TWCoinType coin, TWData* _Nonnull input);

TW_EXTERN_C_END
2 changes: 1 addition & 1 deletion rust/chains/tw_binance/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ tw_evm = { path = "../../tw_evm" }
tw_hash = { path = "../../tw_hash" }
tw_keypair = { path = "../../tw_keypair" }
tw_memory = { path = "../../tw_memory" }
tw_misc = { path = "../../tw_misc" }
tw_misc = { path = "../../tw_misc", features = ["serde"] }
tw_proto = { path = "../../tw_proto" }
17 changes: 14 additions & 3 deletions rust/chains/tw_binance/src/address.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
// Copyright © 2017-2023 Trust Wallet.
// Copyright © 2017-2024 Trust Wallet.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
// file LICENSE at the root of the source code distribution tree.

use serde::Serialize;
use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
use tw_bech32_address::bech32_prefix::Bech32Prefix;
use tw_bech32_address::Bech32Address;
use tw_coin_entry::coin_context::CoinContext;
use tw_coin_entry::coin_entry::CoinAddress;
use tw_coin_entry::error::{AddressError, AddressResult};
use tw_cosmos_sdk::address::CosmosAddress;
use tw_keypair::tw::PublicKey;
use tw_memory::Data;

Expand All @@ -21,7 +22,7 @@ const BNB_KNOWN_HRPS: [&str; 2] = [
"bca",
];

#[derive(Serialize)]
#[derive(Deserialize, PartialEq, Serialize)]
pub struct BinanceAddress(Bech32Address);

impl CoinAddress for BinanceAddress {
Expand All @@ -31,6 +32,16 @@ impl CoinAddress for BinanceAddress {
}
}

impl CosmosAddress for BinanceAddress {
fn from_str_with_coin(coin: &dyn CoinContext, addr: &str) -> AddressResult<Self>
where
Self: Sized,
{
let prefix = None;
Self::from_str_with_coin_and_prefix(coin, addr.to_string(), prefix)
}
}

impl BinanceAddress {
pub const VALIDATOR_HRP: &'static str = "bva";

Expand Down
2 changes: 1 addition & 1 deletion rust/chains/tw_binance/src/amino.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2017-2023 Trust Wallet.
// Copyright © 2017-2024 Trust Wallet.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
Expand Down
22 changes: 18 additions & 4 deletions rust/chains/tw_binance/src/compiler.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// Copyright © 2017-2023 Trust Wallet.
// Copyright © 2017-2024 Trust Wallet.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
// file LICENSE at the root of the source code distribution tree.

use crate::context::BinanceContext;
use crate::modules::preimager::{JsonPreimager, JsonTxPreimage};
use crate::modules::serializer::BinanceAminoSerializer;
use crate::modules::tx_builder::TxBuilder;
Expand All @@ -12,9 +13,12 @@ use crate::transaction::SignerInfo;
use tw_coin_entry::coin_context::CoinContext;
use tw_coin_entry::coin_entry::{PublicKeyBytes, SignatureBytes};
use tw_coin_entry::common::compile_input::SingleSignaturePubkey;
use tw_coin_entry::error::SigningResult;
use tw_coin_entry::error::{SigningError, SigningErrorType, SigningResult};
use tw_coin_entry::signing_output_error;
use tw_keypair::ecdsa::secp256k1;
use tw_cosmos_sdk::modules::serializer::json_serializer::JsonSerializer;
use tw_cosmos_sdk::public_key::secp256k1::Secp256PublicKey;
use tw_cosmos_sdk::public_key::CosmosPublicKey;
use tw_misc::traits::ToBytesVec;
use tw_proto::Binance::Proto;
use tw_proto::TxCompiler::Proto as CompilerProto;

Expand Down Expand Up @@ -69,7 +73,13 @@ impl BinanceCompiler {
public_key,
} = SingleSignaturePubkey::from_sign_pubkey_list(signatures, public_keys)?;
let signature = BinanceSignature::try_from(signature.as_slice())?;
let public_key = secp256k1::PublicKey::try_from(public_key.as_slice())?;
let public_key = Secp256PublicKey::from_bytes(coin, public_key.as_slice())?;

let signature_bytes = signature.to_vec();
let signature_json = JsonSerializer::<BinanceContext>::serialize_signature(
&public_key,
signature_bytes.clone(),
);

let unsigned_tx = TxBuilder::unsigned_tx_from_proto(coin, &input)?;
let signed_tx = unsigned_tx.into_signed(SignerInfo {
Expand All @@ -79,8 +89,12 @@ impl BinanceCompiler {

let encoded_tx = BinanceAminoSerializer::serialize_signed_tx(&signed_tx)?;

let signature_json = serde_json::to_string(&signature_json)
.map_err(|_| SigningError(SigningErrorType::Error_internal))?;
Ok(Proto::SigningOutput {
encoded: encoded_tx.into(),
signature: signature_bytes.into(),
signature_json: signature_json.into(),
..Proto::SigningOutput::default()
})
}
Expand Down
23 changes: 23 additions & 0 deletions rust/chains/tw_binance/src/context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright © 2017-2024 Trust Wallet.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
// file LICENSE at the root of the source code distribution tree.

use crate::address::BinanceAddress;
use tw_cosmos_sdk::context::CosmosContext;
use tw_cosmos_sdk::hasher::sha256_hasher::Sha256Hasher;
use tw_cosmos_sdk::private_key::secp256k1::Secp256PrivateKey;
use tw_cosmos_sdk::public_key::secp256k1::Secp256PublicKey;
use tw_cosmos_sdk::signature::secp256k1::Secp256k1Signature;

pub struct BinanceContext;

impl CosmosContext for BinanceContext {
type Address = BinanceAddress;
/// Binance Beacon chain uses `sha256` hash.
type TxHasher = Sha256Hasher;
type PrivateKey = Secp256PrivateKey;
type PublicKey = Secp256PublicKey;
type Signature = Secp256k1Signature;
}
9 changes: 8 additions & 1 deletion rust/chains/tw_binance/src/entry.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
// Copyright © 2017-2023 Trust Wallet.
// Copyright © 2017-2024 Trust Wallet.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
// file LICENSE at the root of the source code distribution tree.

use crate::address::BinanceAddress;
use crate::compiler::BinanceCompiler;
use crate::modules::wallet_connect::connector::BinanceWalletConnector;
use crate::signer::BinanceSigner;
use std::str::FromStr;
use tw_bech32_address::bech32_prefix::Bech32Prefix;
Expand Down Expand Up @@ -33,6 +34,7 @@ impl CoinEntry for BinanceEntry {
type JsonSigner = NoJsonSigner;
type PlanBuilder = NoPlanBuilder;
type MessageSigner = NoMessageSigner;
type WalletConnector = BinanceWalletConnector;

#[inline]
fn parse_address(
Expand Down Expand Up @@ -88,4 +90,9 @@ impl CoinEntry for BinanceEntry {
) -> Self::SigningOutput {
BinanceCompiler::compile(coin, input, signatures, public_keys)
}

#[inline]
fn wallet_connector(&self) -> Option<Self::WalletConnector> {
Some(BinanceWalletConnector)
}
}
3 changes: 2 additions & 1 deletion rust/chains/tw_binance/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2017-2023 Trust Wallet.
// Copyright © 2017-2024 Trust Wallet.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
Expand All @@ -7,6 +7,7 @@
pub mod address;
pub mod amino;
pub mod compiler;
pub mod context;
pub mod entry;
pub mod modules;
pub mod signature;
Expand Down
3 changes: 2 additions & 1 deletion rust/chains/tw_binance/src/modules/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2017-2023 Trust Wallet.
// Copyright © 2017-2024 Trust Wallet.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
Expand All @@ -7,3 +7,4 @@
pub mod preimager;
pub mod serializer;
pub mod tx_builder;
pub mod wallet_connect;
2 changes: 1 addition & 1 deletion rust/chains/tw_binance/src/modules/preimager.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2017-2023 Trust Wallet.
// Copyright © 2017-2024 Trust Wallet.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
Expand Down
10 changes: 5 additions & 5 deletions rust/chains/tw_binance/src/modules/serializer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2017-2023 Trust Wallet.
// Copyright © 2017-2024 Trust Wallet.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
Expand All @@ -8,7 +8,7 @@ use crate::amino::AminoEncoder;
use crate::transaction::SignedTransaction;
use std::borrow::Cow;
use tw_coin_entry::error::{SigningError, SigningErrorType, SigningResult};
use tw_hash::H264;
use tw_cosmos_sdk::public_key::CosmosPublicKey;
use tw_memory::Data;
use tw_misc::traits::ToBytesVec;
use tw_proto::serialize;
Expand All @@ -27,7 +27,7 @@ impl BinanceAminoSerializer {
.unsigned
.msgs
.iter()
.map(|msg| msg.to_amino_protobuf().map(Cow::from))
.map(|msg| msg.as_ref().to_amino_protobuf().map(Cow::from))
.collect::<SigningResult<Vec<_>>>()?;

let signature = Self::serialize_signature(tx)?;
Expand All @@ -43,7 +43,7 @@ impl BinanceAminoSerializer {
.encode_size_prefixed()?)
}

pub fn serialize_public_key(public_key: H264) -> Data {
pub fn serialize_public_key(public_key: Data) -> Data {
let public_key_len = public_key.len() as u8;
AminoEncoder::new(&PUBLIC_KEY_PREFIX)
// Push the length of the public key.
Expand All @@ -54,7 +54,7 @@ impl BinanceAminoSerializer {

pub fn serialize_signature(signed: &SignedTransaction) -> SigningResult<Data> {
let sign_msg = Proto::Signature {
pub_key: Self::serialize_public_key(signed.signer.public_key.compressed()).into(),
pub_key: Self::serialize_public_key(signed.signer.public_key.to_bytes()).into(),
signature: signed.signer.signature.to_vec().into(),
account_number: signed.unsigned.account_number,
sequence: signed.unsigned.sequence,
Expand Down
Loading
Loading