diff --git a/.gitignore b/.gitignore index 7a5561d7def..9e6a32631ab 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ xcode/ cmake-build-debug/ .cquery_cache/ .cxx/ +CMakeCache.txt +CMakeFiles/ # Dependencies node_modules diff --git a/CMakeLists.txt b/CMakeLists.txt index 151bb0fed14..59675c42667 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,11 @@ project(TrustWalletCore) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") +if(ANDROID) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") +else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++") +endif() set(CMAKE_EXPORT_COMPILE_COMMANDS 1) set(CMAKE_POSITION_INDEPENDENT_CODE ON) @@ -18,6 +22,7 @@ else() set(PREFIX "$ENV{PREFIX}") endif() + include_directories(${PREFIX}/include) link_directories(${PREFIX}/lib) @@ -88,3 +93,19 @@ if(NOT ANDROID AND NOT IOS_PLATFORM AND NOT WASM) endif() configure_file(${CMAKE_CURRENT_SOURCE_DIR}/swift/cpp.xcconfig.in ${CMAKE_CURRENT_SOURCE_DIR}/swift/cpp.xcconfig @ONLY) + +if(ANDROID) + # Workaround: + include_directories(BEFORE SYSTEM + $ENV{NDK_DIR}/sources/android/support/include + $ENV{NDK_DIR}/toolchains/llvm/prebuilt/linux-x86_64/lib64/clang/9.0.8/include # stddef.h + $ENV{NDK_DIR}/sysroot/usr/include + $ENV{NDK_DIR}/sources/cxx-stl/llvm-libc++abi/include + $ENV{NDK_DIR}/sources/cxx-stl/llvm-libc++/include + ) +else() + include_directories(BEFORE SYSTEM + /usr/include/x86_64-linux-gnu/c++/7.5.0 + /usr/include/c++/7.5.0 + ) +endif() diff --git a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/digitalgold/TestDigitalGoldAddress.kt b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/digitalgold/TestDigitalGoldAddress.kt new file mode 100644 index 00000000000..686b33d4ac4 --- /dev/null +++ b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/digitalgold/TestDigitalGoldAddress.kt @@ -0,0 +1,33 @@ +// Copyright © 2017-2020 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. + +package com.trustwallet.core.app.blockchains.digitalgold + +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.* + +class TestDigitalGoldAddress { + + init { + System.loadLibrary("TrustWalletCore") + } + + @Test + fun testAddress() { + // TODO: Check and finalize implementation + + val key = PrivateKey("__PRIVATE_KEY_DATA__".toHexByteArray()) + val pubkey = key.publicKeyEd25519 + val address = AnyAddress(pubkey, CoinType.DIGITALGOLD) + val expected = AnyAddress("__EXPECTED_RESULT_ADDRESS__", CoinType.DIGITALGOLD) + + assertEquals(pubkey.data().toHex(), "0x__EXPECTED_PUBKEY_DATA__") + assertEquals(address.description(), expected.description()) + } +} diff --git a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/digitalgold/TestDigitalGoldSigner.kt b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/digitalgold/TestDigitalGoldSigner.kt new file mode 100644 index 00000000000..b3e2107b3b5 --- /dev/null +++ b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/digitalgold/TestDigitalGoldSigner.kt @@ -0,0 +1,45 @@ +// Copyright © 2017-2020 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. + +package com.trustwallet.core.app.blockchains.digitalgold + +import com.google.protobuf.ByteString +import com.trustwallet.core.app.utils.Numeric +import com.trustwallet.core.app.utils.toHexByteArray +import com.trustwallet.core.app.utils.toHexBytes +import com.trustwallet.core.app.utils.toHexBytesInByteString +import junit.framework.Assert.assertEquals +import org.junit.Test +import wallet.core.jni.BitcoinSigner +import wallet.core.jni.proto.Bitcoin + +class TestDigitalGoldSigner { + + init { + System.loadLibrary("TrustWalletCore") + } + + @Test + fun DigitalGoldTransactionSigning() { + // TODO: Finalize implementation + + //val transfer = DigitalGold.TransferMessage.newBuilder() + // .setTo("...") + // .setAmount(...) + // ... + // .build() + //val signingInput = DigitalGold.SigningInput.newBuilder() + // ... + // .build() + + //val output: DigitalGold.SigningOutput = DigitalGoldSigner.sign(signingInput) + + //assertEquals( + // "__EXPECTED_RESULT_DATA__", + // Numeric.toHexString(output.encoded.toByteArray()) + //) + } +} diff --git a/bootstrap.sh b/bootstrap.sh index f8898e319c4..509b427b5da 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -10,7 +10,7 @@ echo "#### Generating files... ####" tools/generate-files echo "#### Building... ####" -cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=Debug +cmake . -Bbuild -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ make -Cbuild -j12 tests TrezorCryptoTests if [ -x "$(command -v clang-tidy)" ]; then diff --git a/cmake/Protobuf.cmake b/cmake/Protobuf.cmake index b99dd565cd1..7f27286911e 100644 --- a/cmake/Protobuf.cmake +++ b/cmake/Protobuf.cmake @@ -1,5 +1,5 @@ -set(protobuf_SOURCE_DIR ${CMAKE_SOURCE_DIR}/wallet-core/build/local/src/protobuf/protobuf-3.9.0) -set(protobuf_source_dir ${CMAKE_SOURCE_DIR}/wallet-core/build/local/src/protobuf/protobuf-3.9.0) +set(protobuf_SOURCE_DIR ${CMAKE_SOURCE_DIR}/build/local/src/protobuf/protobuf-3.9.0) +set(protobuf_source_dir ${CMAKE_SOURCE_DIR}/build/local/src/protobuf/protobuf-3.9.0) # Updated from https://github.com/protocolbuffers/protobuf/blob/master/cmake/libprotopuf.cmake diff --git a/coins.json b/coins.json index 4c1e7e99ab6..94c2e61ae53 100644 --- a/coins.json +++ b/coins.json @@ -1380,5 +1380,41 @@ "clientPublic": "https://api.elrond.com", "clientDocs": "https://docs.elrond.com" } + }, + { + "id": "dgld", + "name": "DigitalGold", + "symbol": "DGLD", + "decimals": 8, + "blockchain": "Bitcoin", + "derivationPath": "m/44'/452'/0'/0/0", + "curve": "secp256k1", + "publicKeyType": "secp256k1", + "p2pkhPrefix": 38, + "p2shPrefix": 97, + "hrp": "bc", + "publicKeyHasher": "sha256ripemd", + "base58Hasher": "sha256d", + "xpub": "zpub", + "xprv": "zprv", + "explorer": { + "url": "https://explorer.dgld.ch", + "txPath": "/tx/", + "accountPath": "/address/", + "sampleTx": "68e203d1837aad907f4c09b22835e78304a7ae5c4268d0c2487958e3a1858b6e", + "sampleAccount": "g3X4Jwf9WLuBqET7tr2bCkDX3A2FGBrUm8" + }, + "info": { + "url": "https://dgld.ch/", + "client": "https://github.com/goldtokensa/ocean-wallet/releases", + "clientPublic": "", + "clientDocs": "https://github.com/goldtokensa/ocean-wallet/releases" + } } ] + + + + + + diff --git a/docs/coins.md b/docs/coins.md index 7457ad39952..02010656b7d 100644 --- a/docs/coins.md +++ b/docs/coins.md @@ -39,6 +39,7 @@ This list is generated from [./coins.json](../coins.json) | 397 | NEAR | NEAR | | | | 425 | Aion | AION | | | | 434 | Kusama | KSM | | | +| 452 | DigitalGold | DGLD | | | | 457 | Aeternity | AE | | | | 459 | Kava | KAVA | | | | 461 | Filecoin | FIL | | | diff --git a/include/TrustWalletCore/TWCoinType.h b/include/TrustWalletCore/TWCoinType.h index 98095785c80..890919c5f15 100644 --- a/include/TrustWalletCore/TWCoinType.h +++ b/include/TrustWalletCore/TWCoinType.h @@ -81,6 +81,7 @@ enum TWCoinType { TWCoinTypePolkadot = 354, TWCoinTypeFilecoin = 461, TWCoinTypeElrond = 508, + TWCoinTypeDigitalGold = 452, }; /// Returns the blockchain for a coin type. diff --git a/src/Base58.cpp b/src/Base58.cpp index 207809114c3..d11312b3605 100644 --- a/src/Base58.cpp +++ b/src/Base58.cpp @@ -11,6 +11,7 @@ #include #include +#include using namespace TW; @@ -77,7 +78,7 @@ Data Base58::decode(const char* begin, const char* end) const { auto it = begin; // Skip leading spaces. - it = std::find_if_not(it, end, std::isspace); + it = std::find_if_not(it, end, [](unsigned char ch) -> bool { return std::isspace(ch); }); // Skip and count leading zeros. std::size_t zeroes = 0; @@ -118,7 +119,7 @@ Data Base58::decode(const char* begin, const char* end) const { } // Skip trailing spaces. - it = std::find_if_not(it, end, std::isspace); + it = std::find_if_not(it, end, [](unsigned char ch) -> bool { return std::isspace(ch); }); if (it != end) { // Extra charaters at the end return {}; diff --git a/src/Base58Address.h b/src/Base58Address.h index c294f364161..1a887cc9c63 100644 --- a/src/Base58Address.h +++ b/src/Base58Address.h @@ -26,10 +26,13 @@ class Base58Address { std::array bytes; /// Determines whether a collection of bytes makes a valid address. - template - static bool isValid(const T& data) { + static bool isValid(const Data& data) { return data.size() == size; } + /*template + static bool isValid(const T& data) { + return data.size() == size; + }*/ /// Determines whether a string makes a valid address. static bool isValid(const std::string& string) { diff --git a/src/BinaryCoding.h b/src/BinaryCoding.h index f5c6ff18067..36cca69a41e 100644 --- a/src/BinaryCoding.h +++ b/src/BinaryCoding.h @@ -12,6 +12,7 @@ #include #include #include +#include namespace TW { diff --git a/src/Bitcoin/Entry.cpp b/src/Bitcoin/Entry.cpp index 42c39c99cd1..c573f646e7b 100644 --- a/src/Bitcoin/Entry.cpp +++ b/src/Bitcoin/Entry.cpp @@ -22,6 +22,7 @@ bool Entry::validateAddress(TWCoinType coin, const string& address, TW::byte p2p case TWCoinTypeMonacoin: case TWCoinTypeQtum: case TWCoinTypeViacoin: + case TWCoinTypeDigitalGold: case TWCoinTypeBitcoinGold: return SegwitAddress::isValid(address, hrp) || Address::isValid(address, {{p2pkh}, {p2sh}}); @@ -73,6 +74,7 @@ string Entry::deriveAddress(TWCoinType coin, const PublicKey& publicKey, TW::byt case TWCoinTypeQtum: case TWCoinTypeRavencoin: case TWCoinTypeZcoin: + case TWCoinTypeDigitalGold: default: return Address(publicKey, p2pkh).string(); } diff --git a/src/Bitcoin/Entry.h b/src/Bitcoin/Entry.h index 09d5ff27d81..11703246e7f 100644 --- a/src/Bitcoin/Entry.h +++ b/src/Bitcoin/Entry.h @@ -28,6 +28,7 @@ class Entry: public CoinEntry { TWCoinTypeRavencoin, TWCoinTypeViacoin, TWCoinTypeZcoin, + TWCoinTypeDigitalGold, }; } virtual bool validateAddress(TWCoinType coin, const std::string& address, TW::byte p2pkh, TW::byte p2sh, const char* hrp) const; diff --git a/src/Bitcoin/Script.h b/src/Bitcoin/Script.h index 08dfe6bfe28..736b547d8de 100644 --- a/src/Bitcoin/Script.h +++ b/src/Bitcoin/Script.h @@ -13,6 +13,7 @@ #include #include +#include namespace TW::Bitcoin { diff --git a/src/Data.h b/src/Data.h index 4e80e18865a..3592ff89196 100644 --- a/src/Data.h +++ b/src/Data.h @@ -28,6 +28,10 @@ inline Data data(const byte* data, size_t size) { return std::vector(data, data + size); } +inline Data data(byte b) { + return std::vector({b}); +} + inline void append(Data& data, const Data& suffix) { data.insert(data.end(), suffix.begin(), suffix.end()); } diff --git a/src/Encrypt.cpp b/src/Encrypt.cpp index 7492fdb8b54..9782fd42c7f 100644 --- a/src/Encrypt.cpp +++ b/src/Encrypt.cpp @@ -8,6 +8,7 @@ #include "Data.h" #include #include +#include namespace TW::Encrypt { diff --git a/src/Filecoin/Address.cpp b/src/Filecoin/Address.cpp index f12887c612d..06ddb6799eb 100644 --- a/src/Filecoin/Address.cpp +++ b/src/Filecoin/Address.cpp @@ -9,6 +9,8 @@ #include "../Base32.h" #include "../Data.h" +#include + using namespace TW; using namespace TW::Filecoin; diff --git a/src/HDWallet.cpp b/src/HDWallet.cpp index 52d2deab333..bd706095d6e 100644 --- a/src/HDWallet.cpp +++ b/src/HDWallet.cpp @@ -18,6 +18,7 @@ #include #include +#include using namespace TW; diff --git a/src/NEO/ReadData.h b/src/NEO/ReadData.h index 7f7e0a0b4c7..624a1265120 100644 --- a/src/NEO/ReadData.h +++ b/src/NEO/ReadData.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include "../Data.h" #include "../BinaryCoding.h" diff --git a/src/Nebulas/Address.cpp b/src/Nebulas/Address.cpp index bbc81447f43..46f210636f7 100644 --- a/src/Nebulas/Address.cpp +++ b/src/Nebulas/Address.cpp @@ -8,6 +8,7 @@ #include "../Base58.h" #include "../Hash.h" #include "../HexCoding.h" +#include using namespace TW::Nebulas; diff --git a/src/Waves/Address.cpp b/src/Waves/Address.cpp index be51732e937..672d0310595 100644 --- a/src/Waves/Address.cpp +++ b/src/Waves/Address.cpp @@ -13,6 +13,7 @@ #include #include #include +#include using namespace TW; using namespace TW::Waves; diff --git a/src/interface/TWStoredKey.cpp b/src/interface/TWStoredKey.cpp index 28dd3d992c6..3fbfa5f1214 100644 --- a/src/interface/TWStoredKey.cpp +++ b/src/interface/TWStoredKey.cpp @@ -14,6 +14,7 @@ #include #include + using namespace TW::Keystore; struct TWStoredKey* _Nullable TWStoredKeyLoad(TWString* _Nonnull path) { diff --git a/swift/Tests/Blockchains/DigitalGoldTests.swift b/swift/Tests/Blockchains/DigitalGoldTests.swift new file mode 100644 index 00000000000..afa62c10593 --- /dev/null +++ b/swift/Tests/Blockchains/DigitalGoldTests.swift @@ -0,0 +1,28 @@ +// Copyright © 2017-2020 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. + +import TrustWalletCore +import XCTest + +class DigitalGoldTests: XCTestCase { + // TODO: Check and finalize implementation + + func testAddress() { + // TODO: Check and finalize implementation + + let key = PrivateKey(data: Data(hexString: "__PRIVATE_KEY_DATA__")!)! + let pubkey = key.getPublicKeyEd25519() + let address = AnyAddress(publicKey: pubkey, coin: .digitalgold) + let addressFromString = AnyAddress(string: "__ADDRESS_DATA__", coin: .digitalgold)! + + XCTAssertEqual(pubkey.data.hexString, "__EXPECTED_PUBKEY_DATA__") + XCTAssertEqual(address.description, addressFromString.description) + } + + func testSign() { + // TODO: Create implementation + } +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4091767804b..f6acfc476be 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,7 +6,7 @@ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) # Add googletest directly to our build. This defines # the gtest and gtest_main targets. -add_subdirectory(${CMAKE_SOURCE_DIR}/wallet-core/build/local/src/gtest/googletest-release-1.8.1 +add_subdirectory(${CMAKE_SOURCE_DIR}/build/local/src/gtest/googletest-release-1.8.1 ${CMAKE_CURRENT_BINARY_DIR}/googletest-build EXCLUDE_FROM_ALL) diff --git a/tests/DigitalGold/AddressTests.cpp b/tests/DigitalGold/AddressTests.cpp new file mode 100644 index 00000000000..4b74744c586 --- /dev/null +++ b/tests/DigitalGold/AddressTests.cpp @@ -0,0 +1,119 @@ +// Copyright © 2017-2020 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. + +#include "HexCoding.h" +#include "Bitcoin/Address.h" +#include "Bitcoin/Script.h" +#include "Coin.h" +#include "PublicKey.h" +#include "PrivateKey.h" +#include +#include + +using namespace TW; +using namespace TW::Bitcoin; + +static const byte p2pkh = p2pkhPrefix(TWCoinTypeDigitalGold); +static const byte p2sh = p2shPrefix(TWCoinTypeDigitalGold); + +TEST(DigitalGoldAddress, Valid) { + + ASSERT_TRUE(Address::isValid("GJCMxPGMH3LVoGtZ3yEhPYbMVnYwSybBzi", {{p2pkh}, {p2sh}})); + ASSERT_TRUE(Address::isValid("GaLFdPjbDVGcv7v6xuhbvpXUq8mtMkR24y", {{p2pkh}, {p2sh}})); + ASSERT_TRUE(Address::isValid("GfxjHLysUq5XmPqtYPVyzdVm39QSDpFdET", {{p2pkh}, {p2sh}})); + ASSERT_TRUE(Address::isValid("Gdzoxj6QFLDndw5htN2hLJ8JwKRWYHdX2K", {{p2pkh}, {p2sh}})); + ASSERT_TRUE(Address::isValid("GJKt1CQ4wj2i7QTL2VzhXGQ7u7uUXJ7s5A", {{p2pkh}, {p2sh}})); + ASSERT_TRUE(Address::isValid("Gc5JdxYv2k1FfJMr689J66VxQ4yGp97GzZ", {{p2pkh}, {p2sh}})); + ASSERT_TRUE(Address::isValid("GdfXJwBdQUwD1nuySrQeZjFw8KEtPEoBeB", {{p2pkh}, {p2sh}})); + ASSERT_TRUE(Address::isValid("GcSsKzmisNB5KCH6wJr6NZyoSMyydVvi22", {{p2pkh}, {p2sh}})); + ASSERT_TRUE(Address::isValid("GKm9Uj8R6MPqNw2xkhXNYKsvUy46n8E655", {{p2pkh}, {p2sh}})); + ASSERT_TRUE(Address::isValid("GJu16E3CmFdSknrzbKpXacW2MPoLwiesTv", {{p2pkh}, {p2sh}})); + ASSERT_TRUE(Address::isValid("GTWUe2J9amAkhGm6ePrg2knPXYwNZWL2AH", {{p2pkh}, {p2sh}})); + ASSERT_TRUE(Address::isValid("GJBJoGst6SPYweTdE2rLXpc7ky3JaN8s3M", {{p2pkh}, {p2sh}})); + ASSERT_TRUE(Address::isValid("GYPHQbxED8GFtpHkZShNzAxyZDrUVKjPFC", {{p2pkh}, {p2sh}})); + + // TODO: test segwit addresses +} + +TEST(DigitalGoldAddress, Invalid) { + + ASSERT_FALSE(Address::isValid("GZ8fKGGqBZtenPR8hL-----BpMcagkXg5g", {{p2pkh}, {p2sh}})); + ASSERT_FALSE(Address::isValid("1MVk8kVbs7nepTGwbQN1H46UDjSDAUgcRU", {{p2pkh}, {p2sh}})); // valid bitcoin address, but invalid dgld address + + // TODO: Add more tests +} + +TEST(DigitalGoldAddress, FromPrivateKey) { + auto privateKey = PrivateKey(parse_hex("63832fb769a6f12b0a403b8906d6b718a3994b1c1ace78be359a7ff39b3a7362")); + auto address = Address(privateKey.getPublicKey(TWPublicKeyTypeSECP256k1), p2pkh); + ASSERT_EQ(address.string(), "GNxs8kNGP4E18is7TRvjh9WknrStwMmS2N"); +} + +TEST(DigitalGoldAddress, FromPublicKey) { + auto publicKey = PublicKey(parse_hex("028bd49b59eaa0aa4485ef35bc0433cf5071eeb41b229d17c5563d935ca474a9b4"), TWPublicKeyTypeSECP256k1); + auto address = Address(publicKey, p2pkh); + ASSERT_EQ(address.string(), "GSvAp2iiodmfkuS4xcpAyJo7s5xhPGw6YY"); +} + +TEST(DigitalGoldAddress, FromString) { + auto address = Address("GRZ3JdwD4LuiJd2x7kKfFVJr6MdHREj7ie"); + ASSERT_EQ(address.string(), "GRZ3JdwD4LuiJd2x7kKfFVJr6MdHREj7ie"); +} + + +TEST(DigitalGoldAddress, ScriptTest) { + + auto privateKey1 = PrivateKey(parse_hex("63832fb769a6f12b0a403b8906d6b718a3994b1c1ace78be359a7ff39b3a7362")); + + auto address1a = Address(privateKey1.getPublicKey(TWPublicKeyTypeSECP256k1), p2pkh); + auto script1a = Script::buildForAddress(address1a.string(), TWCoinTypeDigitalGold); + ASSERT_FALSE(script1a.isPayToWitnessScriptHash()); + ASSERT_FALSE(script1a.isPayToScriptHash()); + ASSERT_EQ(script1a.bytes.size(), 25); + ASSERT_EQ(hex(script1a.bytes.begin(), script1a.bytes.end()), "76a9143828ccf7696ce8e8c16a397b103f0a4f3b876bf488ac"); + auto hash1a = Data(); + script1a.matchPayToPublicKeyHash(hash1a); + ASSERT_EQ(hash1a.size(), 20); + ASSERT_EQ(hex(hash1a.begin(), hash1a.end()), "3828ccf7696ce8e8c16a397b103f0a4f3b876bf4"); + + auto address1b = Address(privateKey1.getPublicKey(TWPublicKeyTypeSECP256k1), p2sh); + auto script1b = Script::buildForAddress(address1b.string(), TWCoinTypeDigitalGold); + ASSERT_FALSE(script1b.isPayToWitnessScriptHash()); + ASSERT_TRUE(script1b.isPayToScriptHash()); + ASSERT_EQ(script1b.bytes.size(), 23); + ASSERT_EQ(hex(script1b.bytes.begin(), script1b.bytes.end()), "a9143828ccf7696ce8e8c16a397b103f0a4f3b876bf487"); + auto hash1b = Data(); + script1b.matchPayToScriptHash(hash1b); + ASSERT_EQ(hash1b.size(), 20); + ASSERT_EQ(hex(hash1b.begin(), hash1b.end()), "3828ccf7696ce8e8c16a397b103f0a4f3b876bf4"); + + auto privateKey2 = PrivateKey(parse_hex("63832fb769a6f12b0a403b8906d6b718a3994b1c1ace78be359a7ff39b3a7363")); + + auto address2a = Address(privateKey2.getPublicKey(TWPublicKeyTypeSECP256k1), p2pkh); + auto script2a = Script::buildForAddress(address2a.string(), TWCoinTypeDigitalGold); + ASSERT_FALSE(script2a.isPayToWitnessScriptHash()); + ASSERT_FALSE(script2a.isPayToScriptHash()); + ASSERT_EQ(script2a.bytes.size(), 25); + ASSERT_EQ(hex(script2a.bytes.begin(), script2a.bytes.end()), "76a9142f8a97924776e36fafaae12e41cf2b0f7d24597c88ac"); + auto hash2a = Data(); + script2a.matchPayToPublicKeyHash(hash2a); + ASSERT_EQ(hash2a.size(), 20); + ASSERT_EQ(hex(hash2a.begin(), hash2a.end()), "2f8a97924776e36fafaae12e41cf2b0f7d24597c"); + + auto address2b = Address(privateKey2.getPublicKey(TWPublicKeyTypeSECP256k1), p2sh); + auto script2b = Script::buildForAddress(address2b.string(), TWCoinTypeDigitalGold); + ASSERT_FALSE(script2b.isPayToWitnessScriptHash()); + ASSERT_TRUE(script2b.isPayToScriptHash()); + ASSERT_EQ(script2b.bytes.size(), 23); + ASSERT_EQ(hex(script2b.bytes.begin(), script2b.bytes.end()), "a9142f8a97924776e36fafaae12e41cf2b0f7d24597c87"); + auto hash2b = Data(); + script2b.matchPayToScriptHash(hash2b); + ASSERT_EQ(hash2b.size(), 20); + ASSERT_EQ(hex(hash2b.begin(), hash2b.end()), "2f8a97924776e36fafaae12e41cf2b0f7d24597c"); + +} + + diff --git a/tests/DigitalGold/SignerTests.cpp b/tests/DigitalGold/SignerTests.cpp new file mode 100644 index 00000000000..35511aed8d9 --- /dev/null +++ b/tests/DigitalGold/SignerTests.cpp @@ -0,0 +1,217 @@ +// Copyright © 2017-2020 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. + +#include "Bitcoin/Signer.h" +#include "Bitcoin/Address.h" +#include "HexCoding.h" +#include "PrivateKey.h" +#include "PublicKey.h" +#include "Coin.h" +#include "Bitcoin/Script.h" +#include + +#include + +using namespace TW; +using namespace TW::Bitcoin; + + +static const byte p2pkh = p2pkhPrefix(TWCoinTypeDigitalGold); +static const byte p2sh = p2shPrefix(TWCoinTypeDigitalGold); + + +TEST(DigitalGoldSigner, SignP2PKH) { + // Test spending from P2PKH address. A single private key is needed. + + auto inputTxHash = parse_hex("db6b1b20aa0fd7b23880be2ecbd4a98130974cf4748fb66092ac4d3ceb1a5477"); // transaction id to spend from (example, can be anything) + + auto privateKeyFrom = PrivateKey(parse_hex("63832fb769a6f12b0a403b8906d6b718a3994b1c1ace78be359a7ff39b3a7362")); // private key of the owner + auto toAddress = Address("GYPHQbxED8GFtpHkZShNzAxyZDrUVKjPFC"); // destination address + + auto publicKeyFrom = privateKeyFrom.getPublicKey(TWPublicKeyTypeSECP256k1); // public key (from private key) + auto fromAddress = Address(publicKeyFrom, p2pkh); // P2PKH source address (reconstructed from private key) + EXPECT_EQ(fromAddress.string(), "GNxs8kNGP4E18is7TRvjh9WknrStwMmS2N"); + auto redeemScript = Script::buildForAddress(fromAddress.string(), TWCoinTypeDigitalGold); + auto redeemScriptHash = redeemScript.hash(); //Hash::ripemd(Hash::sha256(redeemScript.bytes)); + + // optional sanity checks + auto publicKeyHash = Hash::ripemd(Hash::sha256(publicKeyFrom.bytes)); + EXPECT_EQ(hex(publicKeyHash.begin(), publicKeyHash.end()), "3828ccf7696ce8e8c16a397b103f0a4f3b876bf4"); + auto scriptSig = Script::buildPayToPublicKeyHash(publicKeyHash); + auto scriptSigHash = Hash::ripemd(Hash::sha256(scriptSig.bytes)); + EXPECT_EQ(hex(scriptSigHash.begin(), scriptSigHash.end()), "82472cab708d49bb1e80fae459d6ae0fa34a7bde"); + Data pubKeyHashExtracted; + redeemScript.matchPayToPublicKeyHash(pubKeyHashExtracted); + EXPECT_EQ(hex(pubKeyHashExtracted.begin(), pubKeyHashExtracted.end()), hex(publicKeyHash.begin(), publicKeyHash.end())); + EXPECT_EQ(hex(redeemScriptHash.begin(), redeemScriptHash.end()), hex(scriptSigHash.begin(), scriptSigHash.end())); + + auto changeAddress = Address("GTWUe2J9amAkhGm6ePrg2knPXYwNZWL2AH"); // change address, should belong to the owner + + int inputAmount = 1000; // must cover output amount and the fee, rest will go to the change address + int outputAmount = 600; + + Proto::SigningInput input; + input.set_hash_type(TWBitcoinSigHashTypeAll); + input.set_coin_type(TWCoinTypeDigitalGold); + input.set_amount(outputAmount); // amount to send + input.set_byte_fee(1); + input.set_to_address(toAddress.string()); + input.set_change_address(changeAddress.string()); + + input.add_private_key(privateKeyFrom.bytes.data(), privateKeyFrom.bytes.size()); + (*input.mutable_scripts())[hex(redeemScriptHash.begin(), redeemScriptHash.end())] = std::string(redeemScript.bytes.begin(), redeemScript.bytes.end()); + + Proto::UnspentTransaction* utxo = input.add_utxo(); + utxo->set_amount(inputAmount); // amount to take + utxo->set_script(redeemScript.bytes.data(), redeemScript.bytes.size()); + utxo->mutable_out_point()->set_hash(inputTxHash.data(), inputTxHash.size()); // transaction id + utxo->mutable_out_point()->set_index(1); // index of output of the transaction + utxo->mutable_out_point()->set_sequence(12345678); + + auto plan = Signer::plan(input); + int feeAmount = plan.fee(); + int changeAmount = plan.change(); + + ASSERT_TRUE(feeAmount >= 0); + ASSERT_TRUE(changeAmount >= 0); + + input.set_allocated_plan(new Proto::TransactionPlan(std::move(plan))); + + ASSERT_TRUE(inputAmount == outputAmount + feeAmount + changeAmount); + + auto signature = Signer::sign(input); + + // TODO: match individual fields + auto correct_signed_transaction = "transaction {\n" + " version: 1\n" + " inputs {\n" + " previousOutput {\n" + " hash: \"\\333k\\033 \\252\\017\\327\\2628\\200\\276.\\313\\324\\251\\2010\\227L\\364t\\217\\266`\\222\\254M<\\353\\032Tw\"\n" + " index: 1\n" + " }\n" + " sequence: 12345678\n" + " script: \"G0D\\002 1@\\300\\177\\204}\\002r\\340\\367?a5\\262y\\202\\303\\'\\03377n\\235#P\\242\\376\\321\\215\\034>\\307\\002 {\\033E\\206\\253\\024\\202z\\375+!j\\264\\020\\345\\t8\\222/\\013\\271\\215\\271\\323\\336\\307(\\225\\237H\\356#\\001!\\002E\\036\\201UM\\260Lf_\\345-F2\\335\\232*\\326W]\\272-\\021)\\331(#\\031\\357\\363\\244LI\"\n" + " }\n" + " outputs {\n" + " value: 600\n" + " script: \"v\\251\\024\\237\\200-\\234o\\360:\\\"%\\026Q%N\\255\\\\\\363]\\262\\354\\325\\210\\254\"\n" + " }\n" + " outputs {\n" + " value: 174\n" + " script: \"v\\251\\024j\\003\\326\\\"P\\3748:x\\355\\253>\\246\\244\\3371A%\\207\\212\\210\\254\"\n" + " }\n" + "}\n" + "encoded: \"\\001\\000\\000\\000\\001\\333k\\033 \\252\\017\\327\\2628\\200\\276.\\313\\324\\251\\2010\\227L\\364t\\217\\266`\\222\\254M<\\353\\032Tw\\001\\000\\000\\000jG0D\\002 1@\\300\\177\\204}\\002r\\340\\367?a5\\262y\\202\\303\\'\\03377n\\235#P\\242\\376\\321\\215\\034>\\307\\002 {\\033E\\206\\253\\024\\202z\\375+!j\\264\\020\\345\\t8\\222/\\013\\271\\215\\271\\323\\336\\307(\\225\\237H\\356#\\001!\\002E\\036\\201UM\\260Lf_\\345-F2\\335\\232*\\326W]\\272-\\021)\\331(#\\031\\357\\363\\244LINa\\274\\000\\002X\\002\\000\\000\\000\\000\\000\\000\\031v\\251\\024\\237\\200-\\234o\\360:\\\"%\\026Q%N\\255\\\\\\363]\\262\\354\\325\\210\\254\\256\\000\\000\\000\\000\\000\\000\\000\\031v\\251\\024j\\003\\326\\\"P\\3748:x\\355\\253>\\246\\244\\3371A%\\207\\212\\210\\254\\000\\000\\000\\000\"\n" + "transaction_id: \"dac0ad7a0ee5b91b3eb20910a87001ea31271e800cc2d6c1e08c87b517462d60\"\n"; + + ASSERT_EQ(signature.Utf8DebugString(), correct_signed_transaction); +} + + + +TEST(DigitalGoldSigner, SignP2SH) { + // Test spending from P2SH address. 2-of-3 multisig script is used as example. 3 public keys are needed to generate the address, 2 private keys to spend from it. + + auto inputTxHash = parse_hex("db6b1b20aa0fd7b23880be2ecbd4a98130974cf4748fb66092ac4d3ceb1a5477"); // transaction id to spend from (example, can be anything) + + PrivateKey privateKeyFrom[3] = { + PrivateKey(parse_hex("63832fb769a6f12b0a403b8906d6b718a3994b1c1ace78be359a7ff39b3a7360")), // private key 1 + PrivateKey(parse_hex("63832fb769a6f12b0a403b8906d6b718a3994b1c1ace78be359a7ff39b3a7361")), // private key 2 + PrivateKey(parse_hex("63832fb769a6f12b0a403b8906d6b718a3994b1c1ace78be359a7ff39b3a7362")) // private key 3 + }; + auto toAddress = Address("GYPHQbxED8GFtpHkZShNzAxyZDrUVKjPFC"); // destination address + + std::vector publicKeyFrom; + for(int i = 0; i < 3; i++) { + publicKeyFrom.push_back(privateKeyFrom[i].getPublicKey(TWPublicKeyTypeSECP256k1)); // public key (from private key) + } + + Data redeemScriptSrc; // 2-of-3 multisig redeem script + redeemScriptSrc.push_back(OP_2); + for(int i = 0; i < 3; i++) { + redeemScriptSrc.push_back(publicKeyFrom[i].bytes.size()); + std::copy(publicKeyFrom[i].bytes.begin(), publicKeyFrom[i].bytes.end(), std::back_inserter(redeemScriptSrc)); + } + redeemScriptSrc.push_back(OP_3); + redeemScriptSrc.push_back(OP_CHECKMULTISIG); + + auto redeemScript = Script(std::move(redeemScriptSrc)); + auto redeemScriptHash = redeemScript.hash(); //Hash::ripemd(Hash::sha256(redeemScript.bytes)); + + Data fromAddressSrc; + fromAddressSrc.push_back(p2sh); + std::copy(redeemScriptHash.begin(), redeemScriptHash.end(), std::back_inserter(fromAddressSrc)); + auto fromAddress = Address(fromAddressSrc); + EXPECT_EQ(fromAddress.string(), "gP2d72von4mf3NUyT2EvpMi8TrFd7cYYUt"); + + auto changeAddress = Address("GTWUe2J9amAkhGm6ePrg2knPXYwNZWL2AH"); // change address, should belong to the owner + + int inputAmount = 1000; // must cover output amount and the fee, rest will go to the change address + int outputAmount = 600; + + Proto::SigningInput input; + input.set_hash_type(TWBitcoinSigHashTypeAll); + input.set_coin_type(TWCoinTypeDigitalGold); + input.set_amount(outputAmount); // amount to send + input.set_byte_fee(1); + input.set_to_address(toAddress.string()); + input.set_change_address(changeAddress.string()); + + for(int i = 0; i < 2; i++) { // only 2 private keys of 3 + input.add_private_key(privateKeyFrom[i].bytes.data(), privateKeyFrom[i].bytes.size()); + } + (*input.mutable_scripts())[hex(redeemScriptHash.begin(), redeemScriptHash.end())] = std::string(redeemScript.bytes.begin(), redeemScript.bytes.end()); + + Proto::UnspentTransaction* utxo = input.add_utxo(); + utxo->set_amount(inputAmount); // amount to take + utxo->set_script(redeemScript.bytes.data(), redeemScript.bytes.size()); + utxo->mutable_out_point()->set_hash(inputTxHash.data(), inputTxHash.size()); // source transaction id + utxo->mutable_out_point()->set_index(1); // index of output of the source transaction to spend from + utxo->mutable_out_point()->set_sequence(12345678); + + auto plan = Signer::plan(input); + + int feeAmount = plan.fee(); + int changeAmount = plan.change(); + + ASSERT_TRUE(feeAmount >= 0); + ASSERT_TRUE(changeAmount >= 0); + + // plan can still be modified + + input.set_allocated_plan(new Proto::TransactionPlan(std::move(plan))); + + ASSERT_TRUE(inputAmount == outputAmount + feeAmount + changeAmount); + + auto signature = Signer::sign(input); + + // TODO: match individual fields + auto correct_signed_transaction = "transaction {\n" + " version: 1\n" + " inputs {\n" + " previousOutput {\n" + " hash: \"\\333k\\033 \\252\\017\\327\\2628\\200\\276.\\313\\324\\251\\2010\\227L\\364t\\217\\266`\\222\\254M<\\353\\032Tw\"\n" + " index: 1\n" + " }\n" + " sequence: 12345678\n" + " script: \"\\000H0E\\002!\\000\\304\\263\\240\\375\\326\\250X:C\\3000\\3055\\206\\t\\003\\246\\335\\030\\324\\006\\242;\\372\\201{\\270<\\325\\335\\2175\\002 W\\275(\\207p\\231\\\"\\315\\007\\201w\\263p\\375e\\375\\010\\r8\\316Iy0\\352cF\\366\\241\\363\\325\\226\\251\\001G0D\\002 2\\343\\372A\\226K@\\3420t\\006\\2703\\016\\227]d\\333\\007\\037\\372W\\275\\017H\\227\\306\\202M\\2151\\273\\002 \\017\\217\\276\\362\\020iG\\\\\\347\\364\\375\\306\\263\\317D\\225}\\360\\007\\001 [J\\300\\022\\304^?\\322\\377\\036\\335\\001\"\n" + " }\n" + " outputs {\n" + " value: 600\n" + " script: \"v\\251\\024\\237\\200-\\234o\\360:\\\"%\\026Q%N\\255\\\\\\363]\\262\\354\\325\\210\\254\"\n" + " }\n" + " outputs {\n" + " value: 174\n" + " script: \"v\\251\\024j\\003\\326\\\"P\\3748:x\\355\\253>\\246\\244\\3371A%\\207\\212\\210\\254\"\n" + " }\n" + "}\n" + "encoded: \"\\001\\000\\000\\000\\001\\333k\\033 \\252\\017\\327\\2628\\200\\276.\\313\\324\\251\\2010\\227L\\364t\\217\\266`\\222\\254M<\\353\\032Tw\\001\\000\\000\\000\\222\\000H0E\\002!\\000\\304\\263\\240\\375\\326\\250X:C\\3000\\3055\\206\\t\\003\\246\\335\\030\\324\\006\\242;\\372\\201{\\270<\\325\\335\\2175\\002 W\\275(\\207p\\231\\\"\\315\\007\\201w\\263p\\375e\\375\\010\\r8\\316Iy0\\352cF\\366\\241\\363\\325\\226\\251\\001G0D\\002 2\\343\\372A\\226K@\\3420t\\006\\2703\\016\\227]d\\333\\007\\037\\372W\\275\\017H\\227\\306\\202M\\2151\\273\\002 \\017\\217\\276\\362\\020iG\\\\\\347\\364\\375\\306\\263\\317D\\225}\\360\\007\\001 [J\\300\\022\\304^?\\322\\377\\036\\335\\001Na\\274\\000\\002X\\002\\000\\000\\000\\000\\000\\000\\031v\\251\\024\\237\\200-\\234o\\360:\\\"%\\026Q%N\\255\\\\\\363]\\262\\354\\325\\210\\254\\256\\000\\000\\000\\000\\000\\000\\000\\031v\\251\\024j\\003\\326\\\"P\\3748:x\\355\\253>\\246\\244\\3371A%\\207\\212\\210\\254\\000\\000\\000\\000\"\n" + "transaction_id: \"5b09ae87620f65d7975e98abb0dedf21cb9e97c0d1ff943283999e9a4b7351fb\"\n"; + + ASSERT_EQ(signature.Utf8DebugString(), correct_signed_transaction); +} + + diff --git a/tests/DigitalGold/TWAnyAddressTests.cpp b/tests/DigitalGold/TWAnyAddressTests.cpp new file mode 100644 index 00000000000..8537c7bc5a9 --- /dev/null +++ b/tests/DigitalGold/TWAnyAddressTests.cpp @@ -0,0 +1,19 @@ +// Copyright © 2017-2020 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. + +#include +#include "HexCoding.h" + +#include "../interface/TWTestUtilities.h" +#include + +using namespace TW; + +// TODO: Finalize tests + +TEST(TWDigitalGold, Address) { + // TODO: Finalize test implementation +} diff --git a/tests/DigitalGold/TWAnySignerTests.cpp b/tests/DigitalGold/TWAnySignerTests.cpp new file mode 100644 index 00000000000..593acfd700e --- /dev/null +++ b/tests/DigitalGold/TWAnySignerTests.cpp @@ -0,0 +1,19 @@ +// Copyright © 2017-2020 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. + +#include +#include "HexCoding.h" + +#include "../interface/TWTestUtilities.h" +#include + +using namespace TW; + +// TODO: Finalize tests + +TEST(TWAnySignerDigitalGold, Sign) { + // TODO: Finalize test implementation +} diff --git a/tests/DigitalGold/TWCoinTypeTests.cpp b/tests/DigitalGold/TWCoinTypeTests.cpp new file mode 100644 index 00000000000..835750b1614 --- /dev/null +++ b/tests/DigitalGold/TWCoinTypeTests.cpp @@ -0,0 +1,43 @@ +// Copyright © 2017-2020 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. +// +// This is a GENERATED FILE, changes made here MAY BE LOST. +// Generated one-time (codegen/bin/cointests) +// + +#include "../interface/TWTestUtilities.h" +#include +#include + + +TEST(TWDigitalGoldCoinType, TWCoinTypeConfigurationGetDecimals) { + ASSERT_EQ(TWCoinTypeConfigurationGetDecimals(TWCoinTypeDigitalGold), 8); +} + +TEST(TWDigitalGoldCoinType, TWCoinTypeBlockchain) { + ASSERT_EQ(TWBlockchainBitcoin, TWCoinTypeBlockchain(TWCoinTypeDigitalGold)); +} + +TEST(TWDigitalGoldCoinType, TWCoinTypeXXXPrefix) { + ASSERT_EQ(38, TWCoinTypeP2pkhPrefix(TWCoinTypeDigitalGold)); + ASSERT_EQ(97, TWCoinTypeP2shPrefix(TWCoinTypeDigitalGold)); +} + +TEST(TWDigitalGoldCoinType, TWCoinTypeConfigurationXXX) { + auto symbol = WRAPS(TWCoinTypeConfigurationGetSymbol(TWCoinTypeDigitalGold)); + auto txId = TWStringCreateWithUTF8Bytes("68e203d1837aad907f4c09b22835e78304a7ae5c4268d0c2487958e3a1858b6e"); + auto txUrl = WRAPS(TWCoinTypeConfigurationGetTransactionURL(TWCoinTypeDigitalGold, txId)); + auto accId = TWStringCreateWithUTF8Bytes("g3X4Jwf9WLuBqET7tr2bCkDX3A2FGBrUm8"); + auto accUrl = WRAPS(TWCoinTypeConfigurationGetAccountURL(TWCoinTypeDigitalGold, accId)); + auto id = WRAPS(TWCoinTypeConfigurationGetID(TWCoinTypeDigitalGold)); + auto name = WRAPS(TWCoinTypeConfigurationGetName(TWCoinTypeDigitalGold)); + + ASSERT_EQ(std::string(TWStringUTF8Bytes(symbol.get())), std::string("DGLD")); + ASSERT_EQ(std::string(TWStringUTF8Bytes(txUrl.get())), std::string("https://explorer.dgld.ch/tx/68e203d1837aad907f4c09b22835e78304a7ae5c4268d0c2487958e3a1858b6e")); + ASSERT_EQ(std::string(TWStringUTF8Bytes(accUrl.get())), std::string("https://explorer.dgld.ch/address/g3X4Jwf9WLuBqET7tr2bCkDX3A2FGBrUm8")); + ASSERT_EQ(std::string(TWStringUTF8Bytes(id.get())), std::string("dgld")); + ASSERT_EQ(std::string(TWStringUTF8Bytes(name.get())), std::string("DigitalGold")); +} diff --git a/tests/interface/TWStoredKeyTests.cpp b/tests/interface/TWStoredKeyTests.cpp index 66704ee4c6f..2a023e3d992 100644 --- a/tests/interface/TWStoredKeyTests.cpp +++ b/tests/interface/TWStoredKeyTests.cpp @@ -202,10 +202,11 @@ TEST(TWStoredKey, importInvalidKey) { } TEST(TWStoredKey, removeAccountForCoin) { + const string name = "Test Keystore"; const auto passwordString = WRAPS(TWStringCreateWithUTF8Bytes("password")); const auto password = WRAPD(TWDataCreateWithBytes(reinterpret_cast(TWStringUTF8Bytes(passwordString.get())), TWStringSize(passwordString.get()))); - auto key = TWStoredKeyCreate("Test KeyStore", password.get()); + auto key = TWStoredKeyCreate((const void*)&name, password.get()); auto wallet = TWStoredKeyWallet(key, password.get()); ASSERT_NE(TWStoredKeyAccountForCoin(key, TWCoinTypeEthereum, wallet), nullptr); diff --git a/tests/interface/TWTestUtilities.cpp b/tests/interface/TWTestUtilities.cpp index 2c7412330c8..0db28b1ea1a 100644 --- a/tests/interface/TWTestUtilities.cpp +++ b/tests/interface/TWTestUtilities.cpp @@ -7,6 +7,7 @@ #include "TWTestUtilities.h" #include +#include using namespace std; diff --git a/tools/install-dependencies b/tools/install-dependencies index 9fe3d19c611..623630f6244 100755 --- a/tools/install-dependencies +++ b/tools/install-dependencies @@ -26,7 +26,7 @@ tar xzf release-$GTEST_VERSION.tar.gz # Build gtest cd googletest-release-$GTEST_VERSION -cmake -DCMAKE_INSTALL_PREFIX:PATH=$PREFIX -H. +cmake -DCMAKE_INSTALL_PREFIX:PATH=$PREFIX . make make install diff --git a/trezor-crypto/src/bip32.c b/trezor-crypto/src/bip32.c index b397a89abee..3f5d51c610f 100644 --- a/trezor-crypto/src/bip32.c +++ b/trezor-crypto/src/bip32.c @@ -632,11 +632,11 @@ int hdnode_sign(HDNode *node, const uint8_t *msg, uint32_t msg_len, HasherType h } else if (node->curve == &ed25519_keccak_info) { ed25519_sign_keccak(msg, msg_len, node->private_key, node->public_key + 1, sig); } else if (node->curve == &curve25519_info) { - uint8_t ed25519_public_key[32]; - memset(ed25519_public_key, 0, 32); - curve25519_pk_to_ed25519(ed25519_public_key, node->public_key + 1); - ed25519_sign(msg, msg_len, node->private_key, ed25519_public_key, sig); - const uint8_t sign_bit = ed25519_public_key[31] & 0x80; + uint8_t ed25519_public_key_val[32]; + memset(ed25519_public_key_val, 0, 32); + curve25519_pk_to_ed25519(ed25519_public_key_val, node->public_key + 1); + ed25519_sign(msg, msg_len, node->private_key, ed25519_public_key_val, sig); + const uint8_t sign_bit = ed25519_public_key_val[31] & 0x80; sig[63] = sig[63] & 127; sig[63] |= sign_bit; } diff --git a/walletconsole/lib/Coins.cpp b/walletconsole/lib/Coins.cpp index 368c1b9853e..b59344190b2 100644 --- a/walletconsole/lib/Coins.cpp +++ b/walletconsole/lib/Coins.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #define WRAPS(x) std::shared_ptr(x, TWStringDelete) diff --git a/walletconsole/lib/Util.cpp b/walletconsole/lib/Util.cpp index 01bcba85e9f..7b8b1305a9c 100644 --- a/walletconsole/lib/Util.cpp +++ b/walletconsole/lib/Util.cpp @@ -14,6 +14,7 @@ #include #include #include +#include namespace TW::WalletConsole { diff --git a/walletconsole/lib/Util.h b/walletconsole/lib/Util.h index f86ed09e34e..5522610339b 100644 --- a/walletconsole/lib/Util.h +++ b/walletconsole/lib/Util.h @@ -8,6 +8,7 @@ #include #include +#include namespace TW::WalletConsole {