Skip to content

Commit

Permalink
Sync dev with master (#3308)
Browse files Browse the repository at this point in the history
  • Loading branch information
satoshiotomakan authored Jul 17, 2023
1 parent 7138c7f commit 268b124
Show file tree
Hide file tree
Showing 32 changed files with 501 additions and 95 deletions.
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<img src="docs/banner.png" align="center" title="Trust logo">

Trust Wallet Core is an open source, cross-platform, mobile-focused library
Trust Wallet Core is an open-source, cross-platform, mobile-focused library
implementing low-level cryptographic wallet functionality for a high number of blockchains.
It is a core part of the popular [Trust Wallet](https://trustwallet.com), and some other projects.
Most of the code is C++ with a set of strict C interfaces, and idiomatic interfaces for supported languages:
Expand All @@ -26,7 +26,7 @@ For comprehensive documentation, see [developer.trustwallet.com](https://develop

# Supported Blockchains

Wallet Core supports more than **60** blockchains: Bitcoin, Ethereum, BNB, Cosmos, Solana, and most major blockchain platforms.
Wallet Core supports more than **130** blockchains: Bitcoin, Ethereum, BNB, Cosmos, Solana, and most major blockchain platforms.
The full list is [here](docs/registry.md).

# Building
Expand All @@ -40,7 +40,7 @@ If you want to use wallet core in your project follow these instructions.

## Android

Android releases are hosted on [GitHub packages](https://github.com/trustwallet/wallet-core/packages/700258), you need to add GitHub access token to install it. Please checkout [this installation guide](https://developer.trustwallet.com/wallet-core/integration-guide/android-guide#adding-library-dependency) or `build.gradle` from our [android sample](https://github.com/trustwallet/wallet-core/blob/master/samples/android/build.gradle)
Android releases are hosted on [GitHub packages](https://github.com/trustwallet/wallet-core/packages/700258), you need to add GitHub access token to install it. Please check out [this installation guide](https://developer.trustwallet.com/wallet-core/integration-guide/android-guide#adding-library-dependency) or `build.gradle` from our [android sample](https://github.com/trustwallet/wallet-core/blob/master/samples/android/build.gradle)

Don't forget replacing the version in the code with latest: ![GitHub release (latest by date)](https://img.shields.io/github/v/release/trustwallet/wallet-core)

Expand Down Expand Up @@ -100,7 +100,6 @@ Projects using Trust Wallet Core. Add yours too!
[<img src="https://trustwallet.com/assets/images/trust_logotype.svg" alt="Trust Wallet"/>](https://trustwallet.com)

[Coinpaprika](https://coinpaprika.com/)
| [IFWallet](https://www.ifwallet.com/)
| [crypto.com](https://crypto.com)
| [Alice](https://www.alicedapp.com/)
| [Frontier](https://frontier.xyz/)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class CoinAddressDerivationTests {
ETHEREUM, SMARTCHAIN, POLYGON, OPTIMISM, ZKSYNC, ARBITRUM, ECOCHAIN, AVALANCHECCHAIN, XDAI,
FANTOM, CELO, CRONOSCHAIN, SMARTBITCOINCASH, KUCOINCOMMUNITYCHAIN, BOBA, METIS,
AURORA, EVMOS, MOONRIVER, MOONBEAM, KAVAEVM, KLAYTN, METER, OKXCHAIN, POLYGONZKEVM, SCROLL,
CONFLUXESPACE, ACALAEVM -> assertEquals("0x8f348F300873Fd5DA36950B2aC75a26584584feE", address)
CONFLUXESPACE, ACALAEVM, OPBNBTESTNET -> assertEquals("0x8f348F300873Fd5DA36950B2aC75a26584584feE", address)
RONIN -> assertEquals("ronin:8f348F300873Fd5DA36950B2aC75a26584584feE", address)
ETHEREUMCLASSIC -> assertEquals("0x078bA3228F3E6C08bEEac9A005de0b7e7089aD1c", address)
GOCHAIN -> assertEquals("0x5940ce4A14210d4Ccd0ac206CE92F21828016aC2", address)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import org.junit.Assert.assertEquals
import org.junit.Test
import wallet.core.java.AnySigner
import wallet.core.jni.*
import wallet.core.jni.Cardano.getByronAddress
import wallet.core.jni.Cardano.getStakingAddress
import wallet.core.jni.Cardano.outputMinAdaAmount
import wallet.core.jni.CoinType.CARDANO
Expand Down Expand Up @@ -75,6 +76,60 @@ class TestCardanoSigning {
assertEquals(Numeric.toHexString(txid.toByteArray()), "0x9b5b15e133cd73ccaa85307d2986aebc846505118a2eb4e6111e6b4b67d1f389");
}

/// Successfully broadcasted:
/// https://cardanoscan.io/transaction/0203ce2c91f59f169a26e9ef91254639d2b7911afac9c7c0ae64539f88ba46a5
@Test
fun testSignTransferFromLegacy() {
val privateKey = PrivateKey("98f266d1aac660179bc2f456033941238ee6b2beb8ed0f9f34c9902816781f5a9903d1d395d6ab887b65ea5e344ef09b449507c21a75f0ce8c59d0ed1c6764eba7f484aa383806735c46fd769c679ee41f8952952036a6e2338ada940b8a91f4e890ca4eb6bec44bf751b5a843174534af64d6ad1f44e0613db78a7018781f5aa151d2997f52059466b715d8eefab30a78b874ae6ef4931fa58bb21ef8ce2423d46f19d0fbf75afb0b9a24e31d533f4fd74cee3b56e162568e8defe37123afc4".toHexByteArray())
var publicKey = privateKey.publicKeyEd25519Cardano
var byronAddress = wallet.core.jni.Cardano.getByronAddress(publicKey)

assertEquals(byronAddress, "Ae2tdPwUPEZ6vkqxSjJxaQYmDxHf5DTnxtZ67pFLJGTb9LTnCGkDP6ca3f8")

val message = Cardano.Transfer.newBuilder()
.setToAddress("addr1q90uh2eawrdc9vaemftgd50l28yrh9lqxtjjh4z6dnn0u7ggasexxdyyk9f05atygnjlccsjsggtc87hhqjna32fpv5qeq96ls")
.setChangeAddress("addr1qx55ymlqemndq8gluv40v58pu76a2tp4mzjnyx8n6zrp2vtzrs43a0057y0edkn8lh9su8vh5lnhs4npv6l9tuvncv8swc7t08")
.setAmount(3_000_000)
.build()
val input = Cardano.SigningInput.newBuilder()
.setTransferMessage(message)
.setTtl(190000000)

input.addPrivateKey(ByteString.copyFrom(privateKey.data()))

val outpoint1 = Cardano.OutPoint.newBuilder()
.setTxHash(ByteString.copyFrom(Numeric.hexStringToByteArray("8316e5007d61fb90652cabb41141972a38b5bc60954d602cf843476aa3f67f63")))
.setOutputIndex(0)
.build()
val utxo1 = Cardano.TxInput.newBuilder()
.setOutPoint(outpoint1)
.setAddress("Ae2tdPwUPEZ6vkqxSjJxaQYmDxHf5DTnxtZ67pFLJGTb9LTnCGkDP6ca3f8")
.setAmount(2_500_000)
.build()
input.addUtxos(utxo1)

val outpoint2 = Cardano.OutPoint.newBuilder()
.setTxHash(ByteString.copyFrom(Numeric.hexStringToByteArray("e29392c59c903fefb905730587d22cae8bda30bd8d9aeec3eca082ae77675946")))
.setOutputIndex(0)
.build()
val utxo2 = Cardano.TxInput.newBuilder()
.setOutPoint(outpoint2)
.setAddress("Ae2tdPwUPEZ6vkqxSjJxaQYmDxHf5DTnxtZ67pFLJGTb9LTnCGkDP6ca3f8")
.setAmount(1_700_000)
.build()
input.addUtxos(utxo2)

val output = AnySigner.sign(input.build(), CARDANO, Cardano.SigningOutput.parser())
assertEquals(output.error, SigningError.OK)

val encoded = output.encoded
assertEquals(Numeric.toHexString(encoded.toByteArray()),
"0x83a400828258208316e5007d61fb90652cabb41141972a38b5bc60954d602cf843476aa3f67f6300825820e29392c59c903fefb905730587d22cae8bda30bd8d9aeec3eca082ae77675946000182825839015fcbab3d70db82b3b9da5686d1ff51c83b97e032e52bd45a6ce6fe7908ec32633484b152fa756444e5fc62128210bc1fd7b8253ec5490b281a002dc6c082583901a9426fe0cee6d01d1fe32af650e1e7b5d52c35d8a53218f3d0861531621c2b1ebdf4f11f96da67fdcb0e1d97a7e778566166be55f193c30f1a000f9ec1021a0002b0bf031a0b532b80a20081825820d163c8c4f0be7c22cd3a1152abb013c855ea614b92201497a568c5d93ceeb41e58406a23ab9267867fbf021c1cb2232bc83d2cdd663d651d22d59b6cddbca5cb106d4db99da50672f69a2309ca8a329a3f9576438afe4538b013de4591a6dfcd4d090281845820d163c8c4f0be7c22cd3a1152abb013c855ea614b92201497a568c5d93ceeb41e58406a23ab9267867fbf021c1cb2232bc83d2cdd663d651d22d59b6cddbca5cb106d4db99da50672f69a2309ca8a329a3f9576438afe4538b013de4591a6dfcd4d095820a7f484aa383806735c46fd769c679ee41f8952952036a6e2338ada940b8a91f441a0f6");

val txid = output.txId
assertEquals(Numeric.toHexString(txid.toByteArray()), "0x0203ce2c91f59f169a26e9ef91254639d2b7911afac9c7c0ae64539f88ba46a5");
}

@Test
fun testSignTransferToken1() {
val toToken = Cardano.TokenAmount.newBuilder()
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,19 @@ class TestWebAuthn {
val result = WebAuthn.getPublicKey(attestationObject).data()
assertEquals(Numeric.toHexString(result), "0x04a620a8cfc88fd062b11eab31663e56cad95278bef612959be214d98779f645b84e7b905b42917570148b0432f99ba21f2e7eebe018cbf837247e38150a89f771")
}

@Test
fun testGetRSValues() {
val signature = Numeric.hexStringToByteArray("0x30440220766589b461a838748708cdf88444b21b1fa52b57d70671b4f9bf60ad14b372ec022020cc439c9c20661bfa39bbea24a900ec1484b2395eb065ead8ef4e273144a57d")
val result = WebAuthn.getRSValues(signature)
assertEquals(Numeric.toHexString(result), "0x766589b461a838748708cdf88444b21b1fa52b57d70671b4f9bf60ad14b372ec20cc439c9c20661bfa39bbea24a900ec1484b2395eb065ead8ef4e273144a57d")
}

@Test
fun testReconstructOriginalMessage() {
val authenticatorData = Numeric.hexStringToByteArray("0x1a70842af8c1feb7133b81e6a160a6a2be45ee057f0eb6d3f7f5126daa202e071d00000000")
val clientDataJSON = Numeric.hexStringToByteArray("0x7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a224e5549794f5545774d6b45744e554535517930304d6b5a424c546847516a4174517a52474f4441794d3045304f546b30222c226f726967696e223a2268747470733a2f2f747275737477616c6c65742e636f6d227d")
val result = WebAuthn.reconstructOriginalMessage(authenticatorData, clientDataJSON)
assertEquals(Numeric.toHexString(result), "0x3254cdbd677e6e31e75d2135bad0cf56440d7c6b108c141a3509d76ce45c6731")
}
}
1 change: 1 addition & 0 deletions docs/registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ This list is generated from [./registry.json](../registry.json)
| 2301 | Qtum | QTUM | <img src="https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/qtum/info/logo.png" width="32" /> | <https://qtum.org> |
| 2718 | Nebulas | NAS | <img src="https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/nebulas/info/logo.png" width="32" /> | <https://nebulas.io> |
| 3030 | Hedera | HBAR | <img src="https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/hedera/info/logo.png" width="32" /> | <https://hedera.com/> |
| 5611 | OpBNB testnet | tBNB | <img src="https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/opbnb/info/logo.png" width="32" /> | <https://opbnb.bnbchain.org/en> |
| 6060 | GoChain | GO | <img src="https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/gochain/info/logo.png" width="32" /> | <https://gochain.io> |
| 8964 | NULS | NULS | <img src="https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/nuls/info/logo.png" width="32" /> | <https://nuls.io> |
| 14001 | WAX | WAXP | <img src="https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/wax/info/logo.png" width="32" /> | <http://wax.io> |
Expand Down
6 changes: 6 additions & 0 deletions include/TrustWalletCore/TWCardano.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,10 @@ TWString *_Nullable TWCardanoOutputMinAdaAmount(TWString *_Nonnull toAddress, TW
TW_EXPORT_STATIC_METHOD
TWString *_Nonnull TWCardanoGetStakingAddress(TWString *_Nonnull baseAddress) TW_VISIBILITY_DEFAULT;

/// Return the legacy(byron) address.
/// \param publicKey A valid public key with TWPublicKeyTypeED25519Cardano type.
/// \return the legacy(byron) address, as string, or empty string on error.
TW_EXPORT_STATIC_METHOD
TWString *_Nonnull TWCardanoGetByronAddress(struct TWPublicKey *_Nonnull publicKey);

TW_EXTERN_C_END
1 change: 1 addition & 0 deletions include/TrustWalletCore/TWCoinType.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ enum TWCoinType {
TWCoinTypeConfluxeSpace = 1030,
TWCoinTypeAcala = 787,
TWCoinTypeAcalaEVM = 10000787,
TWCoinTypeOpBNBtestnet = 5611,
};

/// Returns the blockchain for a coin type.
Expand Down
15 changes: 15 additions & 0 deletions include/TrustWalletCore/TWWebAuthn.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,19 @@ struct TWWebAuthn;
/// \return Public key.
TW_EXPORT_STATIC_METHOD
struct TWPublicKey *_Nullable TWWebAuthnGetPublicKey(TWData *_Nonnull attestationObject);

/// Uses ASN parser to extract r and s values from a webauthn signature
///
/// \param signature ASN encoded webauthn signature: https://www.w3.org/TR/webauthn-2/#sctn-signature-attestation-types
/// \return Concatenated r and s values.
TW_EXPORT_STATIC_METHOD
TWData *_Nonnull TWWebAuthnGetRSValues(TWData *_Nonnull signature);

/// Reconstructs the original message that was signed via P256 curve. Can be used for signature validation.
///
/// \param authenticatorData Authenticator Data: https://www.w3.org/TR/webauthn-2/#authenticator-data
/// \param clientDataJSON clientDataJSON: https://www.w3.org/TR/webauthn-2/#dom-authenticatorresponse-clientdatajson
/// \return original messages.
TW_EXPORT_STATIC_METHOD
TWData *_Nonnull TWWebAuthnReconstructOriginalMessage(TWData* _Nonnull authenticatorData, TWData* _Nonnull clientDataJSON);
TW_EXTERN_C_END
30 changes: 30 additions & 0 deletions registry.json
Original file line number Diff line number Diff line change
Expand Up @@ -3960,6 +3960,36 @@
"documentation": "https://doc.confluxnetwork.org/docs/espace"
}
},
{
"id": "opbnb",
"name": "OpBNB testnet",
"coinId": 5611,
"chainId": "5611",
"symbol": "tBNB",
"decimals": 18,
"blockchain": "Ethereum",
"derivation": [
{
"path": "m/44'/60'/0'/0/0"
}
],
"curve": "secp256k1",
"publicKeyType": "secp256k1Extended",
"addressHasher": "keccak256",
"explorer": {
"url": "https://opbnbscan.com",
"txPath": "/tx/",
"accountPath": "/address/",
"sampleTx": "0x788ea8fb4a82dae957f1d3b18af3cd0bbde55a276e66bd17af8c869f24c03a0f",
"sampleAccount": "0x4eaf936c172b5e5511959167e8ab4f7031113ca3"
},
"info": {
"url": "https://opbnb.bnbchain.org/en",
"source": "https://github.com/bnb-chain/opbnb",
"rpc": "https://opbnb-testnet-rpc.bnbchain.org",
"documentation": "https://docs.bnbchain.org/opbnb-docs"
}
},
{
"id": "stratis",
"name": "Stratis",
Expand Down
2 changes: 1 addition & 1 deletion samples/kmp/shared/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation("com.trustwallet:wallet-core-kotlin:3.2.3")
implementation("com.trustwallet:wallet-core-kotlin:3.2.5")
}
}
val commonTest by getting {
Expand Down
12 changes: 6 additions & 6 deletions src/Cardano/AddressV2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,26 @@ bool AddressV2::parseAndCheck(const std::string& addr, Data& root_out, Data& att
// Decode Bas58, decode payload + crc, decode root, attr
Data base58decoded = Base58::decode(addr);
if (base58decoded.empty()) {
throw std::invalid_argument("Invalid address: could not Base58 decode");
return false;
}
auto elems = Cbor::Decode(base58decoded).getArrayElements();
if (elems.size() < 2) {
throw std::invalid_argument("Could not parse address payload from CBOR data");
return false;
}
auto tag = elems[0].getTagValue();
if (tag != PayloadTag) {
throw std::invalid_argument("wrong tag value");
return false;
}
Data payload = elems[0].getTagElement().getBytes();
uint64_t crcPresent = (uint32_t)elems[1].getValue();
uint32_t crcComputed = TW::Crc::crc32(payload);
if (crcPresent != crcComputed) {
throw std::invalid_argument("CRC mismatch");
return false;
}
// parse payload, 3 elements
auto payloadElems = Cbor::Decode(payload).getArrayElements();
if (payloadElems.size() < 3) {
throw std::invalid_argument("Could not parse address root and attrs from CBOR data");
return false;
}
root_out = payloadElems[0].getBytes();
attrs_out = payloadElems[1].encoded(); // map, but encoded as bytes
Expand Down Expand Up @@ -105,7 +105,7 @@ std::string AddressV2::string() const {

Data AddressV2::keyHash(const TW::Data& xpub) {
if (xpub.size() != 64) {
throw std::invalid_argument("invalid xpub length");
return {};
}
// hash of following Cbor-array: [0, [0, xpub], {} ]
// 3rd entry map is empty map for V2, contains derivation path for V1
Expand Down
Loading

0 comments on commit 268b124

Please sign in to comment.