Skip to content

Commit

Permalink
Merge branch 'master' into s/bitcoin-dust-amount
Browse files Browse the repository at this point in the history
  • Loading branch information
satoshiotomakan committed Feb 16, 2024
2 parents 977bff0 + 7523c98 commit 33ae5c4
Show file tree
Hide file tree
Showing 56 changed files with 2,271 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.trustwallet.core.app.blockchains.solana

import com.google.protobuf.ByteString
import com.trustwallet.core.app.utils.toHex
import com.trustwallet.core.app.utils.toHexByteArray
import org.junit.Assert.assertEquals
import org.junit.Test
import wallet.core.jni.Base58
import wallet.core.java.AnySigner
import wallet.core.jni.CoinType.SOLANA
import wallet.core.jni.SolanaTransaction
import wallet.core.jni.DataVector
import wallet.core.jni.proto.Common.SigningError
import wallet.core.jni.proto.Solana
import wallet.core.jni.proto.Solana.SigningOutput

class TestSolanaTransaction {

init {
System.loadLibrary("TrustWalletCore")
}

@Test
fun testUpdateBlockhashAndSign() {
val encodedTx = "AnQTYwZpkm3fs4SdLxnV6gQj3hSLsyacpxDdLMALYWObm722f79IfYFTbZeFK9xHtMumiDOWAM2hHQP4r/GtbARpncaXgOVFv7OgbRLMbuCEJHO1qwcdCbtH72VzyzU8yw9sqqHIAaCUE8xaQTgT6Z5IyZfeyMe2QGJIfOjz65UPAgACBssq8Im1alV3N7wXGODL8jLPWwLhTuCqfGZ1Iz9fb5tXlMOJD6jUvASrKmdtLK/qXNyJns2Vqcvlk+nfJYdZaFpIWiT/tAcEYbttfxyLdYxrLckAKdVRtf1OrNgtZeMCII4SAn6SYaaidrX/AN3s/aVn/zrlEKW0cEUIatHVDKtXO0Qss5EhV/E6kz0BNCgtAytf/s0Botvxt3kGCN8ALqcG3fbh12Whk9nL4UbO63msHLSF7V9bN5E6jPWFfv8Aqe6sdLXiXSDILEtzckCjkjchiSf6zVGpMYiAE5BE2IqHAQUEAgQDAQoMoA8AAAAAAAAG"
val newBlockhash = "CyPYVsYWrsJNfVpi8aazu7WsrswNFuDd385z6GNoBGUg"

val myPrivateKey = "7f0932159226ddec9e1a4b0b8fe7cdc135049f9e549a867d722aa720dd64f32e".toHexByteArray()
val feePayerPrivateKey = "4b9d6f57d28b06cbfa1d4cc710953e62d653caf853415c56ffd9d150acdeb7f7".toHexByteArray()

val privateKeys = DataVector()
privateKeys.add(myPrivateKey)
privateKeys.add(feePayerPrivateKey)

val outputData = SolanaTransaction.updateBlockhashAndSign(encodedTx, newBlockhash, privateKeys)
val output = SigningOutput.parseFrom(outputData)

assertEquals(output.error, SigningError.OK)
val expectedString = "Ajzc/Tke0CG8Cew5qFa6xZI/7Ya3DN0M8Ige6tKPsGzhg8Bw9DqL18KUrEZZ1F4YqZBo4Rv+FsDT8A7Nss7p4A6BNVZzzGprCJqYQeNg0EVIbmPc6mDitNniHXGeKgPZ6QZbM4FElw9O7IOFTpOBPvQFeqy0vZf/aayncL8EK/UEAgACBssq8Im1alV3N7wXGODL8jLPWwLhTuCqfGZ1Iz9fb5tXlMOJD6jUvASrKmdtLK/qXNyJns2Vqcvlk+nfJYdZaFpIWiT/tAcEYbttfxyLdYxrLckAKdVRtf1OrNgtZeMCII4SAn6SYaaidrX/AN3s/aVn/zrlEKW0cEUIatHVDKtXO0Qss5EhV/E6kz0BNCgtAytf/s0Botvxt3kGCN8ALqcG3fbh12Whk9nL4UbO63msHLSF7V9bN5E6jPWFfv8AqbHiki6ThNH3auuyZPQpJntnN0mA//56nMpK/6HIuu8xAQUEAgQDAQoMoA8AAAAAAAAG"
assertEquals(output.encoded, expectedString)
}
}
16 changes: 16 additions & 0 deletions include/TrustWalletCore/TWBarz.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,20 @@ TWData *_Nonnull TWBarzGetInitCode(TWString* _Nonnull factory, struct TWPublicKe
/// \return Bytes of the formatted signature
TW_EXPORT_STATIC_METHOD
TWData *_Nonnull TWBarzGetFormattedSignature(TWData* _Nonnull signature, TWData* _Nonnull challenge, TWData* _Nonnull authenticatorData, TWString* _Nonnull clientDataJSON);

/// Returns the final hash to be signed by Barz for signing messages & typed data
///
/// \param msgHash Original msgHash
/// \param barzAddress The address of Barz wallet signing the message
/// \param chainId The chainId of the network the verification will happen
/// \return The final hash to be signed
TW_EXPORT_STATIC_METHOD
TWData *_Nonnull TWBarzGetPrefixedMsgHash(TWData* _Nonnull msgHash, TWString* _Nonnull barzAddress, uint32_t chainId);

/// Returns the encoded diamondCut function call for Barz contract upgrades
///
/// \param input The serialized data of DiamondCutInput
/// \return The encoded bytes of diamondCut function call
TW_EXPORT_STATIC_METHOD
TWData *_Nonnull TWBarzGetDiamondCutCode(TWData *_Nonnull input);
TW_EXTERN_C_END
33 changes: 33 additions & 0 deletions include/TrustWalletCore/TWSolanaTransaction.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: Apache-2.0
//
// Copyright © 2017 Trust Wallet.

#pragma once

#include "TWBase.h"
#include "TWData.h"
#include "TWDataVector.h"
#include "TWString.h"

TW_EXTERN_C_BEGIN

TW_EXPORT_STRUCT
struct TWSolanaTransaction;

/// Decode Solana transaction, update the recent blockhash and re-sign the transaction.
///
/// # Warning
///
/// This is a temporary solution. It will be removed when `Solana.proto` supports
/// direct transaction signing.
///
/// \param encodedTx base64 encoded Solana transaction.
/// \param recentBlockhash base58 encoded recent blockhash.
/// \param privateKeys list of private keys that should be used to re-sign the transaction.
/// \return serialized `Solana::Proto::SigningOutput`.
TW_EXPORT_STATIC_METHOD
TWData *_Nonnull TWSolanaTransactionUpdateBlockhashAndSign(TWString *_Nonnull encodedTx,
TWString *_Nonnull recentBlockhash,
const struct TWDataVector *_Nonnull privateKeys);

TW_EXTERN_C_END
26 changes: 26 additions & 0 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = [
"chains/tw_greenfield",
"chains/tw_native_evmos",
"chains/tw_native_injective",
"chains/tw_solana",
"chains/tw_thorchain",
"tw_any_coin",
"tw_aptos",
Expand Down
17 changes: 17 additions & 0 deletions rust/chains/tw_solana/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "tw_solana"
version = "0.1.0"
edition = "2021"

[dependencies]
bincode = "1.3.3"
serde = { version = "1.0", features = ["derive"] }
tw_coin_entry = { path = "../../tw_coin_entry" }
tw_encoding = { path = "../../tw_encoding" }
tw_hash = { path = "../../tw_hash" }
tw_keypair = { path = "../../tw_keypair" }
tw_memory = { path = "../../tw_memory" }
tw_proto = { path = "../../tw_proto" }

[dev-dependencies]
serde_json = "1.0"
82 changes: 82 additions & 0 deletions rust/chains/tw_solana/src/address.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// SPDX-License-Identifier: Apache-2.0
//
// Copyright © 2017 Trust Wallet.

use crate::SOLANA_ALPHABET;
use serde::de::Error as DeError;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt;
use std::str::FromStr;
use tw_coin_entry::coin_entry::CoinAddress;
use tw_coin_entry::error::{AddressError, AddressResult};
use tw_encoding::base58;
use tw_hash::H256;
use tw_keypair::tw;
use tw_memory::Data;

#[derive(Clone, Copy)]
pub struct SolanaAddress {
bytes: H256,
}

impl SolanaAddress {
pub fn with_public_key(public_key: &tw::PublicKey) -> AddressResult<SolanaAddress> {
let bytes = public_key
.to_ed25519()
.ok_or(AddressError::PublicKeyTypeMismatch)?
.to_bytes();
Ok(SolanaAddress { bytes })
}

pub fn with_public_key_bytes(bytes: H256) -> SolanaAddress {
SolanaAddress { bytes }
}

pub fn bytes(&self) -> H256 {
self.bytes
}
}

impl CoinAddress for SolanaAddress {
#[inline]
fn data(&self) -> Data {
self.bytes.to_vec()
}
}

impl FromStr for SolanaAddress {
type Err = AddressError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let bytes =
base58::decode(s, &SOLANA_ALPHABET).map_err(|_| AddressError::FromBase58Error)?;
let bytes = H256::try_from(bytes.as_slice()).map_err(|_| AddressError::InvalidInput)?;
Ok(SolanaAddress { bytes })
}
}

impl fmt::Display for SolanaAddress {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let encoded = base58::encode(self.bytes.as_slice(), &SOLANA_ALPHABET);
write!(f, "{}", encoded)
}
}

impl Serialize for SolanaAddress {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.to_string().serialize(serializer)
}
}

impl<'de> Deserialize<'de> for SolanaAddress {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let addr_str = String::deserialize(deserializer)?;
SolanaAddress::from_str(&addr_str).map_err(|e| DeError::custom(format!("{e:?}")))
}
}
50 changes: 50 additions & 0 deletions rust/chains/tw_solana/src/compiler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: Apache-2.0
//
// Copyright © 2017 Trust Wallet.

use tw_coin_entry::coin_context::CoinContext;
use tw_coin_entry::coin_entry::{PublicKeyBytes, SignatureBytes};
use tw_coin_entry::error::SigningResult;
use tw_coin_entry::signing_output_error;
use tw_proto::Solana::Proto;
use tw_proto::TxCompiler::Proto as CompilerProto;

pub struct SolanaCompiler;

impl SolanaCompiler {
#[inline]
pub fn preimage_hashes(
coin: &dyn CoinContext,
input: Proto::SigningInput<'_>,
) -> CompilerProto::PreSigningOutput<'static> {
Self::preimage_hashes_impl(coin, input)
.unwrap_or_else(|e| signing_output_error!(CompilerProto::PreSigningOutput, e))
}

fn preimage_hashes_impl(
_coin: &dyn CoinContext,
_input: Proto::SigningInput<'_>,
) -> SigningResult<CompilerProto::PreSigningOutput<'static>> {
todo!()
}

#[inline]
pub fn compile(
coin: &dyn CoinContext,
input: Proto::SigningInput<'_>,
signatures: Vec<SignatureBytes>,
public_keys: Vec<PublicKeyBytes>,
) -> Proto::SigningOutput<'static> {
Self::compile_impl(coin, input, signatures, public_keys)
.unwrap_or_else(|e| signing_output_error!(Proto::SigningOutput, e))
}

fn compile_impl(
_coin: &dyn CoinContext,
_input: Proto::SigningInput<'_>,
_signatures: Vec<SignatureBytes>,
_public_keys: Vec<PublicKeyBytes>,
) -> SigningResult<Proto::SigningOutput<'static>> {
todo!()
}
}
Loading

0 comments on commit 33ae5c4

Please sign in to comment.