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

implement zilliqa bech32 address #445

Merged
merged 6 commits into from
May 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions .codacy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
exclude_paths:
- 'codegen/**'
- 'tools/**'
- 'trezor-crypto/**'
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Trust Wallet Core is a cross-platform library that implements low-level cryptogr
[![Linux status](https://dev.azure.com/TrustWallet/Trust%20Wallet%20Core/_apis/build/status/Wallet%20Core%20Linux)](https://dev.azure.com/TrustWallet/Trust%20Wallet%20Core/_build/latest?definitionId=24)
[![JavaScript status](https://dev.azure.com/TrustWallet/Trust%20Wallet%20Core/_apis/build/status/Wallet%20Core%20JavaScript)](https://dev.azure.com/TrustWallet/Trust%20Wallet%20Core/_build?definitionId=29)


[![Codacy Badge](https://api.codacy.com/project/badge/Grade/82e76f6ea4ba4f0d9029e8846c04c093)](https://www.codacy.com/app/hewigovens/wallet-core?utm_source=github.com&utm_medium=referral&utm_content=TrustWallet/wallet-core&utm_campaign=Badge_Grade)
![Codecov](https://codecov.io/gh/TrustWallet/wallet-core/branch/master/graph/badge.svg)
![GitHub](https://img.shields.io/github/license/TrustWallet/wallet-core.svg)
![Maven Central](https://img.shields.io/maven-central/v/com.trustwallet.walletcore/walletcore.svg)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class CoinAddressDerivationTests {
STEEM -> assertEquals("STM6WSusVTidc1e7TbLjhqQPYctbsndTRwXHpi82gMuJyKEkJVLvg", address)
EOS -> assertEquals("EOS6hs8sRvGSzuQtq223zwJipMzqTJpXUVjyvHPvPwBSZWWrJTJkg", address)
IOTEX -> assertEquals("io1qw9cccecw09q7p5kzyqtuhfhvah2mhfrc84jfk", address)
ZILLIQA -> assertEquals("0xDdb41006F7B6FA8e5FBF06A71c01F789FeBC66e8", address)
ZILLIQA -> assertEquals("zil1mk6pqphhkmaguhalq6n3cq0h38ltcehg0rfmv6", address)
SEMUX -> assertEquals("0xfe604170382452f77bc922bc19eb4b53504b09c2", address)
DEXON -> assertEquals("0x6F3E6a6dDf2C2B4B32B8Bb452eA3F36B2BB489BF", address)
ZELCASH -> assertEquals("t1UKbRPzL4WN8Rs8aZ8RNiWoD2ftCMHKGUf", address)
Expand Down
2 changes: 2 additions & 0 deletions include/TrustWalletCore/TWHRP.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ enum TWHRP {
TWHRPCosmos /* "cosmos" */,
TWHRPGroestlcoin /* "grs" */,
TWHRPQtum /* "qtum" */,
TWHRPZilliqa /* "zilliqa" */,
};

static const char *_Nonnull HRP_BINANCE = "bnb";
Expand All @@ -33,6 +34,7 @@ static const char *_Nonnull HRP_COSMOS = "cosmos";
static const char *_Nonnull HRP_GROESTLCOIN = "grs";
static const char *_Nonnull HRP_VIACOIN = "via";
static const char *_Nonnull HRP_QTUM = "qc";
static const char *_Nonnull HRP_ZILLIQA = "zil";

const char *_Nullable stringForHRP(enum TWHRP hrp);
enum TWHRP hrpForString(const char *_Nonnull string);
Expand Down
4 changes: 4 additions & 0 deletions include/TrustWalletCore/TWZilliqaAddress.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,8 @@ void TWZilliqaAddressDelete(struct TWZilliqaAddress *_Nonnull address);
TW_EXPORT_PROPERTY
TWString *_Nonnull TWZilliqaAddressDescription(struct TWZilliqaAddress *_Nonnull address);

/// Returns the key hash.
TW_EXPORT_PROPERTY
TWData *_Nonnull TWZilliqaAddressKeyHash(struct TWZilliqaAddress *_Nonnull address);

TW_EXTERN_C_END
2 changes: 1 addition & 1 deletion js/tests/utils/CoinAddressDerivation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ describe('CoinAddressDerivation', () => {
case CoinType.LUX: expect('LYL6SZG8S6dyXRFT8Bw4FHUoVef3cWCoPi').to.equal(address); break;
case CoinType.QTUM: expect('QhceuaTdeCZtcxmVc6yyEDEJ7Riu5gWFoF').to.equal(address); break;
case CoinType.NULS: expect('NsdtNvsfmPerWk4BhcapHTB3LptF8Sbe').to.equal(address); break;
case CoinType.ZILLIQA: expect('0xDdb41006F7B6FA8e5FBF06A71c01F789FeBC66e8').to.equal(address); break;
case CoinType.ZILLIQA: expect('zil1mk6pqphhkmaguhalq6n3cq0h38ltcehg0rfmv6').to.equal(address); break;
case CoinType.SEMUX: expect('0xfe604170382452f77bc922bc19eb4b53504b09c2').to.equal(address); break;
}
};
Expand Down
2 changes: 1 addition & 1 deletion src/Coin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ bool TW::validateAddress(TWCoinType coin, const std::string& string) {
return Zcash::TAddress::isValid(string, {{Zcash::TAddress::staticPrefix, TWP2PKHPrefixZcashT}, {Zcash::TAddress::staticPrefix, TWP2SHPrefixZcashT}});

case TWCoinTypeZilliqa:
return Zilliqa::Address::isValid(string);
return Zilliqa::isValidAddress(string);

case TWCoinTypeNano:
return Nano::Address::isValid(string);
Expand Down
47 changes: 6 additions & 41 deletions src/Zilliqa/Address.cpp
Original file line number Diff line number Diff line change
@@ -1,42 +1,7 @@
#include "Address.h"
#include "AddressChecksum.h"
#include "stdint.h"
#include "../HexCoding.h"

using namespace TW::Zilliqa;

bool Address::isValid(const std::string& string) {
if (string.size() != 42 || string[0] != '0' || string[1] != 'x') {
return false;
}
const auto data = parse_hex(string);
return Address::isValid(data);
}

Address::Address(const std::string& string) {
if (!isValid(string)) {
throw std::invalid_argument("Invalid address data");
}
const auto data = parse_hex(string);
std::copy(data.begin(), data.end(), bytes.begin());
}
// Copyright © 2017-2019 Trust.
//
// 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.

Address::Address(const PublicKey& publicKey) {
if (publicKey.type != TWPublicKeyTypeSECP256k1) {
throw std::invalid_argument("Ziliqa::Address needs SECP256k1 public key");
}
const auto data =
publicKey.hash({}, static_cast<Data (*)(const byte*, const byte*)>(Hash::sha256), false);
std::copy(data.end() - Address::size, data.end(), bytes.begin());
}

Address::Address(const Data& data) {
if (!isValid(data)) {
throw std::invalid_argument("Invalid address data");
}
std::copy(data.begin(), data.end(), bytes.begin());
}

std::string Address::string() const {
return checksumed(*this);
}
#include "Address.h"
49 changes: 21 additions & 28 deletions src/Zilliqa/Address.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,38 @@
#pragma once

#include "../PublicKey.h"
#include "../Cosmos/Address.h"

#include <string>

namespace TW::Zilliqa {

class Address {
public:
/// Number of bytes in an address.
static const size_t size = 20;

/// Address data followed by the public key
std::array<uint8_t, size> bytes;
#include <TrustWalletCore/TWHRP.h>

/// Determines whether a collection of bytes makes a valid address.
static bool isValid(const Data& data) { return data.size() == size; }
#include <string>

/// Determines whether a string makes a valid address.
static bool isValid(const std::string& string);
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-function"

/// Initializes an address from a string representation.
explicit Address(const std::string& string);
namespace TW::Zilliqa {

/// Initializes an address with a collection of bytes.
explicit Address(const Data& data);
static bool isValidAddress(const std::string& address) {
return Cosmos::Address::isValid(address, HRP_ZILLIQA);
}

/// Initializes an address from a public key.
explicit Address(const PublicKey& publicKey);
static Cosmos::Address Address(const PublicKey& publicKey) {
const auto hashed = Hash::sha256(publicKey.bytes);
auto keyHash = Data(20);
std::copy(hashed.end() - 20, hashed.end(), keyHash.begin());

/// Returns a string representation of the address. 20-bytes hex-encoded
std::string string() const;
};
return Cosmos::Address(HRP_ZILLIQA, keyHash);
}

inline bool operator==(const Address& lhs, const Address& rhs) {
return lhs.bytes == rhs.bytes;
}
static Cosmos::Address Address(const Data& keyHash) {
return Cosmos::Address(HRP_ZILLIQA, keyHash);
}

} // namespace TW::Zilliqa

#pragma clang diagnostic pop

/// Wrapper for C interface.
struct TWZilliqaAddress {
TW::Zilliqa::Address impl;
TW::Cosmos::Address impl;
};
6 changes: 3 additions & 3 deletions src/Zilliqa/AddressChecksum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ using namespace TW;
using namespace TW::Zilliqa;

/// see https://github.com/Zilliqa/Zilliqa/blob/1c53b792c7ae44f7b77366536a7e2f73a3eade6a/src/libServer/AddressChecksum.h
std::string Zilliqa::checksumed(const Address& address) {
const auto addressString = hex(address.bytes);
const auto hash = hex(Hash::sha256(address.bytes));
std::string Zilliqa::checksumed(const Data& bytes) {
const auto addressString = hex(bytes);
const auto hash = hex(Hash::sha256(bytes));

uint256_t temp_1 = 1;
uint256_t v("0x" + hash);
Expand Down
6 changes: 3 additions & 3 deletions src/Zilliqa/AddressChecksum.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@

#pragma once

#include "Address.h"
#include "../Data.h"
#include <string>

namespace TW::Zilliqa {

std::string checksumed(const Address& address);
std::string checksumed(const Data& address);

} // namespace TW::Ethereum
} // namespace TW::Zilliqa
5 changes: 2 additions & 3 deletions src/Zilliqa/Signer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,12 @@ Data Signer::getPreImage(const Proto::SigningInput& input) noexcept {
auto internal = ZilliqaMessage::ProtoTransactionCoreInfo();

const auto key = PrivateKey(Data(input.private_key().begin(), input.private_key().end()));
const auto address = Address(input.to_address());

const auto address = Cosmos::Address::decode(input.to_address());
const auto pubKey = key.getPublicKey(TWPublicKeyTypeSECP256k1);

internal.set_version(input.version());
internal.set_nonce(input.nonce());
internal.set_toaddr(address.bytes.data(), address.bytes.size());
internal.set_toaddr(address.first.keyHash.data(), address.first.keyHash.size());

auto sender = new ZilliqaMessage::ByteArray();
sender->set_data(pubKey.bytes.data(), pubKey.bytes.size());
Expand Down
3 changes: 3 additions & 0 deletions src/interface/TWHRP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const char* stringForHRP(enum TWHRP hrp) {
case TWHRPCosmos: return HRP_COSMOS;
case TWHRPGroestlcoin: return HRP_GROESTLCOIN;
case TWHRPQtum: return HRP_QTUM;
case TWHRPZilliqa: return HRP_ZILLIQA;
default: return nullptr;
}
}
Expand All @@ -39,6 +40,8 @@ enum TWHRP hrpForString(const char *_Nonnull string) {
return TWHRPGroestlcoin;
} else if (std::strcmp(string, HRP_QTUM) == 0) {
return TWHRPQtum;
} else if (std::strcmp(string, HRP_ZILLIQA) == 0) {
return TWHRPZilliqa;
} else {
return TWHRPUnknown;
}
Expand Down
12 changes: 9 additions & 3 deletions src/interface/TWZilliqaAddress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,17 @@ bool TWZilliqaAddressEqual(struct TWZilliqaAddress *_Nonnull lhs, struct TWZilli

bool TWZilliqaAddressIsValidString(TWString *_Nonnull string) {
auto s = reinterpret_cast<const std::string*>(string);
return Address::isValid(*s);
return Zilliqa::isValidAddress(*s);
}

struct TWZilliqaAddress *_Nullable TWZilliqaAddressCreateWithString(TWString *_Nonnull string) {
auto s = reinterpret_cast<const std::string*>(string);
if (!Address::isValid(*s)) {
auto dec = Cosmos::Address::decode(*s);
if (!dec.second || dec.first.hrp != HRP_ZILLIQA) {
return nullptr;
}
return new TWZilliqaAddress{ Address(*s) };

return new TWZilliqaAddress{ Address(dec.first.keyHash) };
}

struct TWZilliqaAddress *_Nonnull TWZilliqaAddressCreateWithPublicKey(struct TWPublicKey *_Nonnull publicKey) {
Expand All @@ -47,3 +49,7 @@ TWString *_Nonnull TWZilliqaAddressDescription(struct TWZilliqaAddress *_Nonnull
const auto string = address->impl.string();
return TWStringCreateWithUTF8Bytes(string.c_str());
}

TWData *_Nonnull TWZilliqaAddressKeyHash(struct TWZilliqaAddress *_Nonnull address) {
return TWDataCreateWithBytes(address->impl.keyHash.data(), address->impl.keyHash.size());
}
13 changes: 12 additions & 1 deletion swift/Tests/Blockchains/ZilliqaTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ import XCTest
import TrustWalletCore

class ZilliqaTests: XCTestCase {

func testAddress() {
let data = Data(hexString: "029d25b68a18442590e113132a34bb524695c4291d2c49abf2e4cdd7d98db862c3")!
let pubKey = PublicKey(data: data, type: .secp256k1)!
let address = ZilliqaAddress(publicKey: pubKey)
let address2 = ZilliqaAddress(string: "zil10lx2eurx5hexaca0lshdr75czr025cevqu83uz")!

XCTAssertEqual(address.keyHash.hexString, "7FCcaCf066a5F26Ee3AFfc2ED1FA9810Deaa632C".lowercased())
XCTAssertEqual(address.description, address2.description)
}

func testSigner() {

let privateKey = PrivateKey(data: Data(hexString: "0x68ffa8ec149ce50da647166036555f73d57f662eb420e154621e5f24f6cf9748")!)!
Expand All @@ -15,7 +26,7 @@ class ZilliqaTests: XCTestCase {
let input = ZilliqaSigningInput.with {
$0.version = TWZilliqaTxVersion
$0.nonce = 2
$0.toAddress = "0x7FCcaCf066a5F26Ee3AFfc2ED1FA9810Deaa632C"
$0.toAddress = "zil10lx2eurx5hexaca0lshdr75czr025cevqu83uz"
$0.amount = Data(hexString: "e8d4a51000")!
$0.gasPrice = Data(hexString: "3b9aca00")!
$0.gasLimit = 1
Expand Down
2 changes: 1 addition & 1 deletion swift/Tests/CoinAddressDerivationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ class CoinAddressDerivationTests: XCTestCase {
let expectedResult = "io1qw9cccecw09q7p5kzyqtuhfhvah2mhfrc84jfk"
AssetCoinDerivation(coin, expectedResult, derivedAddress, address)
case .zilliqa:
let expectedResult = "0xDdb41006F7B6FA8e5FBF06A71c01F789FeBC66e8"
let expectedResult = "zil1mk6pqphhkmaguhalq6n3cq0h38ltcehg0rfmv6"
AssetCoinDerivation(coin, expectedResult, derivedAddress, address)
case .semux:
let expectedResult = "0xfe604170382452f77bc922bc19eb4b53504b09c2"
Expand Down
2 changes: 1 addition & 1 deletion swift/Tests/HDWalletTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ class HDWalletTests: XCTestCase {
let address = zil.deriveAddress(privateKey: key)

XCTAssertEqual(key.data.hexString, "b49a9fb16cd2b46ee538be807f712073009ea528e407a25a4bf91a63c3e49f99")
XCTAssertEqual(address.description, "0x65E1a9341E08d10E6f3C00930CE879c5bF980319")
XCTAssertEqual(address.description, "zil1vhs6jdq7prgsumeuqzfse6recklesqcesfe685")
}

func testSignHash() {
Expand Down
3 changes: 2 additions & 1 deletion tests/CoinTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
namespace TW {

TEST(Coin, ValidateAddressZilliqa) {
EXPECT_TRUE(validateAddress(TWCoinTypeZilliqa, "0x91cddcebe846ce4d47712287eee53cf17c2cfb77"));
EXPECT_TRUE(validateAddress(TWCoinTypeZilliqa, "zil1j8xae6lggm8y63m3y2r7aefu797ze7mhzulnqg"));
EXPECT_FALSE(validateAddress(TWCoinTypeZilliqa, "0x91cddcebe846ce4d47712287eee53cf17c2cfb77"));
EXPECT_FALSE(validateAddress(TWCoinTypeZilliqa, "91cddcebe846ce4d47712287eee53cf17c2cfb77"));
EXPECT_FALSE(validateAddress(TWCoinTypeZilliqa, "0x"));
EXPECT_FALSE(validateAddress(TWCoinTypeZilliqa, ""));
Expand Down
Loading