Skip to content

Commit

Permalink
[WalletConnect/BNB]: Add support for WalletConnect signing requests (#…
Browse files Browse the repository at this point in the history
…3632)

* [WalletConnect/BNB]: Add `WalletConnectSigner` optional module

* [WalletConnect/BNB]: Implement `cosmos_signAmino` handler

* TODO fix compilation error

* [WalletConnect/BNB]: POC

* [WalletConnect/BNB]: Move `TxBuilder` implementation

* [WalletConnect/BNB]: Finalize `WalletConnector` in `CoinEntry`

* [WalletConnect/BNB]: Add `tw_wallet_connect_request_parse` FFI

* [WalletConnect/BNB]: Add `signature` and `signature_json` to Binance::SigningOutput

* [WalletConnect/BNB]: Add `TWWalletConnectRequestParse` C FFI

* Improve WalletConnect.proto interface

* [WalletConnect/BNB]: Add Android test

* [WalletConnect/BNB]: Add iOS test

* [WalletConnect/BNB]: Update the year in Copyright

* [WalletConnect/BNB]: Fix codegen-v2 template

* [WalletConnect/BNB]: Minor changes

* [CI] Trigger CI

* [WalletConnect/BNB]: Fix C++ tests

---------

Co-authored-by: Sztergbaum Roman <[email protected]>
  • Loading branch information
satoshiotomakan and Milerius authored Jan 10, 2024
1 parent 03e5082 commit 8f8a266
Show file tree
Hide file tree
Showing 74 changed files with 1,734 additions and 863 deletions.
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

0 comments on commit 8f8a266

Please sign in to comment.