Skip to content

Commit

Permalink
Aeternity fixes (#551)
Browse files Browse the repository at this point in the history
*   fix rlp encoding when int = 0

*  add tests RLP encoding of transaction int properties zero cases

*  update aeternity explorer url

*  clean up comments, fix test

*  add real address test case to ValidateAddressAeternity

* Use bytes in Aeternity.proto

* Fix signature encoding
  • Loading branch information
Defuera authored and hewigovens committed Jul 24, 2019
1 parent a3aee3b commit 6359763
Show file tree
Hide file tree
Showing 14 changed files with 147 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.trustwallet.core.app.blockchains.aeternity

import com.google.protobuf.ByteString
import com.trustwallet.core.app.utils.toHexByteArray
import com.trustwallet.core.app.utils.toHexBytesInByteString
import junit.framework.Assert.assertEquals
import org.junit.Test
Expand All @@ -17,8 +19,8 @@ class TestAeternitySigner {
val signingInput = Aeternity.SigningInput.newBuilder()
.setFromAddress("ak_2p5878zbFhxnrm7meL7TmqwtvBaqcBddyp5eGzZbovZ5FeVfcw")
.setToAddress("ak_Egp9yVdpxmvAfQ7vsXGvpnyfNq71msbdUpkMNYGTeTe8kPL3v")
.setAmount(10L)
.setFee(2e13.toLong())
.setAmount(ByteString.copyFrom("0a".toHexByteArray()))
.setFee(ByteString.copyFrom("12309ce54000".toHexByteArray()))
.setPayload("Hello World")
.setTtl(82757)
.setNonce(49)
Expand All @@ -33,7 +35,7 @@ class TestAeternitySigner {
)
assertEquals(
output.signature,
"sg_2dlw1eTrh79Yri5+urBSwVMJ86dSvCVtWc/nxIJrhIehxLzbtEdddjNyGJFc700p09KSd01oVTrpoCfiFsFvB3kDla0="
"sg_VW42qDPP3MMNFAStYaumjZz7mC7BZYpbNa15E57ejqUe7JdQFWCiX65eLNUpGMpt8tSpfgCfkYzcaFppqx7W75CrcWdC8"
)
}
}
4 changes: 2 additions & 2 deletions coins.json
Original file line number Diff line number Diff line change
Expand Up @@ -1014,11 +1014,11 @@
"derivationPath": "m/44'/457'/0'/0'/0'",
"curve": "ed25519",
"publicKeyType": "ed25519",
"explorer": "https://www.aeknow.org/block/transaction/",
"explorer": "https://explorer.aepps.com/#/tx/",
"info": {
"url": "https://aeternity.com",
"client": "https://github.com/aeternity/aeternity",
"clientPublic": "",
"clientPublic": "https://sdk-mainnet.aepps.com",
"clientDocs": "http://aeternity.com/api-docs/"
}
},
Expand Down
6 changes: 3 additions & 3 deletions js/tests/blockchain/aeternity/AeternitySigner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ describe('AeternitySigner', () => {
const privateKey = fromHexString("4646464646464646464646464646464646464646464646464646464646464646");

const input = TW.Aeternity.Proto.SigningInput.create({
amount: Long.fromNumber(10),
fee: Long.fromNumber(2e13),
amount: fromHexString("0a"),
fee: fromHexString("12309ce54000"),
fromAddress: "ak_2p5878zbFhxnrm7meL7TmqwtvBaqcBddyp5eGzZbovZ5FeVfcw",
nonce: Long.fromNumber(49),
payload: "Hello World",
Expand All @@ -24,7 +24,7 @@ describe('AeternitySigner', () => {

const output = AeternitySigner.sign(input);

expect(output.signature).to.equal("sg_2dlw1eTrh79Yri5+urBSwVMJ86dSvCVtWc/nxIJrhIehxLzbtEdddjNyGJFc700p09KSd01oVTrpoCfiFsFvB3kDla0=");
expect(output.signature).to.equal("sg_VW42qDPP3MMNFAStYaumjZz7mC7BZYpbNa15E57ejqUe7JdQFWCiX65eLNUpGMpt8tSpfgCfkYzcaFppqx7W75CrcWdC8");
expect(output.encoded).to.equal("tx_+KkLAfhCuEDZ2XDV5OuHv1iuLn66sFLBUwnzp1K8JW1Zz+fEgmuEh6HEvNu0R112M3IYkVzvTSnT0pJ3TWhVOumgJ+IWwW8HuGH4XwwBoQHuk6T2b40WuBm7m+uf/M383BQS6H/uajJMKpmh4OZxSKEBHxOjsIvwAUAGYqaLadh194A87EwIZH9u1dhMeJe9UKMKhhIwnOVAAIMBQ0Uxi0hlbGxvIFdvcmxkDZqNSg==");
});

Expand Down
8 changes: 4 additions & 4 deletions src/Aeternity/Signer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "Signer.h"
#include "Address.h"
#include "Base58.h"
#include "Base64.h"
#include "HexCoding.h"
#include "Identifiers.h"
Expand All @@ -25,13 +26,13 @@ Proto::SigningOutput Signer::sign(const TW::PrivateKey &privateKey, Transaction

/// sign ed25519
auto sigRaw = privateKey.sign(msg, TWCurveED25519);
auto signature = finalize(Identifiers::prefixSignature, sigRaw);
auto signature = Identifiers::prefixSignature + Base58::bitcoin.encodeCheck(sigRaw);

/// encode the message using rlp
auto rlpTxRaw = buildRlpTxRaw(txRlp, sigRaw);

/// encode the rlp message with the prefix
auto signedEncodedTx = finalize(Identifiers::prefixTransaction, rlpTxRaw);
auto signedEncodedTx = encodeBase64WithChecksum(Identifiers::prefixTransaction, rlpTxRaw);

return createProtoOutput(signature, signedEncodedTx);
}
Expand Down Expand Up @@ -65,8 +66,7 @@ Proto::SigningOutput Signer::createProtoOutput(std::string &signature, const std
return output;
}

/// Encode a byte array into base64 with checksum and a prefix
std::string Signer::finalize(const std::string &prefix, const TW::Data &rawTx) {
std::string Signer::encodeBase64WithChecksum(const std::string &prefix, const TW::Data &rawTx) {
auto checksum = Hash::sha256(Hash::sha256(rawTx));
std::vector<unsigned char> checksumPart(checksum.begin(), checksum.begin() + checkSumSize);

Expand Down
4 changes: 2 additions & 2 deletions src/Aeternity/Signer.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ class Signer {

static Proto::SigningOutput createProtoOutput(std::string &signature, const std::string &signedTx);

/// Encode a byte array into base64 with checksum and a prefix
static std::string finalize(const std::string &prefix, const TW::Data &rawTx);
/// Encode a byte array into base64 with prefix and a checksum
static std::string encodeBase64WithChecksum(const std::string &prefix, const TW::Data &rawTx);
};

} // namespace TW::Aeternity
Expand Down
18 changes: 12 additions & 6 deletions src/Aeternity/Transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,16 @@ Data Transaction::encode() {
append(encoded, Ethereum::RLP::encode(Identifiers::rlpMessageVersion));
append(encoded, Ethereum::RLP::encode(buildTag(sender_id)));
append(encoded, Ethereum::RLP::encode(buildTag(recipient_id)));
append(encoded, Ethereum::RLP::encode(amount));
append(encoded, Ethereum::RLP::encode(fee));
append(encoded, Ethereum::RLP::encode(ttl));
append(encoded, Ethereum::RLP::encode(nonce));
append(encoded, encodeSafeZero(amount));
append(encoded, encodeSafeZero(fee));
append(encoded, encodeSafeZero(ttl));
append(encoded, encodeSafeZero(nonce));
append(encoded, Ethereum::RLP::encode(payload));

const Data &raw = Ethereum::RLP::encodeList(encoded);
return raw;
}

//// buildIDTag assemble an id() object
//// see https://github.com/aeternity/protocol/blob/epoch-v0.22.0/serializations.md#the-id-type
TW::Data Transaction::buildTag(const std::string &address) {
auto payload = address.substr(Identifiers::prefixTransaction.size(), address.size());

Expand All @@ -41,3 +39,11 @@ TW::Data Transaction::buildTag(const std::string &address) {

return data;
}

TW::Data Transaction::encodeSafeZero(uint256_t value) {
if (value == 0) {
return Ethereum::RLP::encode(Data{0});
} else {
return Ethereum::RLP::encode(value);
}
}
21 changes: 15 additions & 6 deletions src/Aeternity/Transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <Data.h>
#include <string>
#include <uint256.h>

namespace TW::Aeternity {

Expand All @@ -18,9 +19,9 @@ class Transaction {

std::string recipient_id;

uint64_t amount;
uint256_t amount;

uint64_t fee;
uint256_t fee;

std::string payload;

Expand All @@ -32,24 +33,32 @@ class Transaction {
Transaction(
std::string &sender_id,
std::string &recipientId,
uint64_t amount,
uint64_t fee,
uint256_t amount,
uint256_t fee,
std::string &payload,
uint64_t ttl,
uint64_t nonce
)
: sender_id(sender_id)
, recipient_id(recipientId)
, amount(amount)
, fee(fee)
, amount(std::move(amount))
, fee(std::move(fee))
, payload(payload)
, ttl(ttl)
, nonce(nonce){};

Data encode();

//// buildIDTag assemble an id() object
//// see https://github.com/aeternity/protocol/blob/epoch-v0.22.0/serializations.md#the-id-type
static Data buildTag(const std::string &address);

/// Awternity network does not accept zero int values as rlp param,
/// instead empty byte array should be encoded
/// see https://forum.aeternity.com/t/invalid-tx-error-on-mainnet-goggle-says-it-looks-good/4118/5?u=defuera
static Data encodeSafeZero(uint256_t value);


};

} // namespace TW::Aeternity
3 changes: 2 additions & 1 deletion src/interface/TWAeternitySigner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "../Aeternity/Signer.h"
#include "../Aeternity/Transaction.h"
#include "../proto/Aeternity.pb.h"
#include "../uint256.h"
#include <TrustWalletCore/TWAeternitySigner.h>

using namespace TW;
Expand All @@ -21,7 +22,7 @@ TW_Aeternity_Proto_SigningOutput TWAeternitySignerSign(TW_Aeternity_Proto_Signin
std::string recipient_id = input.to_address();
std::string payload = input.payload();

auto tx = Transaction(sender_id, recipient_id, input.amount(), input.fee(), payload, input.ttl(), input.nonce());
auto tx = Transaction(sender_id, recipient_id, load(input.amount()), load(input.fee()), payload, input.ttl(), input.nonce());

auto output = Signer::sign(privateKey, tx);

Expand Down
16 changes: 8 additions & 8 deletions src/proto/Aeternity.proto
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@ option java_package = "wallet.core.jni.proto";

// Input data necessary to create a signed transaction.
message SigningInput {
//Address of the sender with "ak_" prefix
// Address of the sender with "ak_" prefix
string from_address = 1;

//Address of the recipient with "ak_" prefix
// Address of the recipient with "ak_" prefix
string to_address = 2;

uint64 amount = 3;
bytes amount = 3;

uint64 fee = 4;
bytes fee = 4;

//Message, optional
// Message, optional
string payload = 5;

//Time to live
// Time to live until block height
uint64 ttl = 6;

uint64 nonce = 7;
Expand All @@ -28,8 +28,8 @@ message SigningInput {

// Transaction signing output.
message SigningOutput {
// Signed and encoded transaction bytes.
// Signed and encoded transaction bytes, Base64 with checksum
string encoded = 1;
// Signature.
// Signature, Base58 with checksum
string signature = 2;
}
6 changes: 3 additions & 3 deletions swift/Tests/Blockchains/AeternityTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ class AeternityTests: XCTestCase {
let input = AeternitySigningInput.with {
$0.fromAddress = "ak_2p5878zbFhxnrm7meL7TmqwtvBaqcBddyp5eGzZbovZ5FeVfcw"
$0.toAddress = "ak_Egp9yVdpxmvAfQ7vsXGvpnyfNq71msbdUpkMNYGTeTe8kPL3v"
$0.amount = 10
$0.fee = 20000000000000
$0.amount = Data(hexString: "0a")!
$0.fee = Data(hexString: "12309ce54000")!
$0.payload = "Hello World"
$0.ttl = 82757
$0.nonce = 49
Expand All @@ -35,7 +35,7 @@ class AeternityTests: XCTestCase {

let output = AeternitySigner.sign(input: input)

XCTAssertEqual(output.signature, "sg_2dlw1eTrh79Yri5+urBSwVMJ86dSvCVtWc/nxIJrhIehxLzbtEdddjNyGJFc700p09KSd01oVTrpoCfiFsFvB3kDla0=")
XCTAssertEqual(output.signature, "sg_VW42qDPP3MMNFAStYaumjZz7mC7BZYpbNa15E57ejqUe7JdQFWCiX65eLNUpGMpt8tSpfgCfkYzcaFppqx7W75CrcWdC8")

// swiftlint:disable:next line_length
XCTAssertEqual(output.encoded, "tx_+KkLAfhCuEDZ2XDV5OuHv1iuLn66sFLBUwnzp1K8JW1Zz+fEgmuEh6HEvNu0R112M3IYkVzvTSnT0pJ3TWhVOumgJ+IWwW8HuGH4XwwBoQHuk6T2b40WuBm7m+uf/M383BQS6H/uajJMKpmh4OZxSKEBHxOjsIvwAUAGYqaLadh194A87EwIZH9u1dhMeJe9UKMKhhIwnOVAAIMBQ0Uxi0hlbGxvIFdvcmxkDZqNSg==")
Expand Down
60 changes: 57 additions & 3 deletions tests/Aeternity/SignerTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@

#include <Aeternity/Address.h>
#include <gtest/gtest.h>
#include <uint256.h>

using namespace TW;
using namespace TW::Aeternity;

TEST(AeternitySigner, Sign) {
std::string sender_id = "ak_2p5878zbFhxnrm7meL7TmqwtvBaqcBddyp5eGzZbovZ5FeVfcw";
std::string recipient_id = "ak_Egp9yVdpxmvAfQ7vsXGvpnyfNq71msbdUpkMNYGTeTe8kPL3v";
uint64_t amount = 10;
double fee = 2e13;
uint256_t amount = 10;
uint256_t fee = 20000000000000;
std::string payload = "Hello World";
uint64_t ttl = 82757;
uint64_t nonce = 49;
Expand All @@ -27,6 +28,59 @@ TEST(AeternitySigner, Sign) {
auto privateKey = PrivateKey(parse_hex("4646464646464646464646464646464646464646464646464646464646464646"));

auto result = Signer::sign(privateKey, transaction);
EXPECT_EQ(result.signature(), "sg_2dlw1eTrh79Yri5+urBSwVMJ86dSvCVtWc/nxIJrhIehxLzbtEdddjNyGJFc700p09KSd01oVTrpoCfiFsFvB3kDla0=");
EXPECT_EQ(result.signature(), "sg_VW42qDPP3MMNFAStYaumjZz7mC7BZYpbNa15E57ejqUe7JdQFWCiX65eLNUpGMpt8tSpfgCfkYzcaFppqx7W75CrcWdC8");
EXPECT_EQ(result.encoded(), "tx_+KkLAfhCuEDZ2XDV5OuHv1iuLn66sFLBUwnzp1K8JW1Zz+fEgmuEh6HEvNu0R112M3IYkVzvTSnT0pJ3TWhVOumgJ+IWwW8HuGH4XwwBoQHuk6T2b40WuBm7m+uf/M383BQS6H/uajJMKpmh4OZxSKEBHxOjsIvwAUAGYqaLadh194A87EwIZH9u1dhMeJe9UKMKhhIwnOVAAIMBQ0Uxi0hlbGxvIFdvcmxkDZqNSg==");
}

TEST(AeternitySigner, SignTxWithZeroTtl) {
std::string sender_id = "ak_2p5878zbFhxnrm7meL7TmqwtvBaqcBddyp5eGzZbovZ5FeVfcw";
std::string recipient_id = "ak_Egp9yVdpxmvAfQ7vsXGvpnyfNq71msbdUpkMNYGTeTe8kPL3v";
uint256_t amount = 10;
uint256_t fee = 20000000000000;
std::string payload = "Hello World";
uint64_t ttl = 0;
uint64_t nonce = 49;

auto transaction = Transaction(sender_id, recipient_id, amount, fee, payload, ttl, nonce);
auto privateKey = PrivateKey(parse_hex("4646464646464646464646464646464646464646464646464646464646464646"));

auto result = Signer::sign(privateKey, transaction);
EXPECT_EQ(result.signature(), "sg_7qJK868bqEZ5ciC2P3WCKYfhayvKTHvPsz3bdPgpfF3Ky7yNg9f8k22A3gxjjSm9afa6JmP8TJpF4GJkFh2k7gGaog9KS");
EXPECT_EQ(result.encoded(), "tx_+KYLAfhCuEA0OgWhpq/VfS6ksMS+Df4ewZxIITEhjaaMOiyT0aRuAEe6b5+d2cQtzoyz58NNr+N4MFowctrGXrCrrkhNIywLuF74XAwBoQHuk6T2b40WuBm7m+uf/M383BQS6H/uajJMKpmh4OZxSKEBHxOjsIvwAUAGYqaLadh194A87EwIZH9u1dhMeJe9UKMKhhIwnOVAAAAxi0hlbGxvIFdvcmxkjoDNvQ==");
}

TEST(AeternitySigner, SignTxWithZeroAmount) {
std::string sender_id = "ak_2p5878zbFhxnrm7meL7TmqwtvBaqcBddyp5eGzZbovZ5FeVfcw";
std::string recipient_id = "ak_Egp9yVdpxmvAfQ7vsXGvpnyfNq71msbdUpkMNYGTeTe8kPL3v";
uint256_t amount = 0;
uint256_t fee = 20000000000000;
std::string payload = "Zero amount test";
uint64_t ttl = 113579;
uint64_t nonce = 7;

auto transaction = Transaction(sender_id, recipient_id, amount, fee, payload, ttl, nonce);
auto privateKey = PrivateKey(parse_hex("4646464646464646464646464646464646464646464646464646464646464646"));

auto result = Signer::sign(privateKey, transaction);
EXPECT_EQ(result.signature(), "sg_ShWvujPnyKBT1Ng2X5k6XSchVK8Bq7LYEisPMH11DUoPkXZcooBzqw81j9j5JewoFFpT9xEhUptj1azcLA21ogURYh4Lz");
EXPECT_EQ(result.encoded(), "tx_+K4LAfhCuEDEbeoiVYmJCXm91KNfZXOvZMoT9x/sZja09EXZmErFBxm52b1IVoM4806Zr+TsliAYzUyKfUUFo3jGfXEPdZ8PuGb4ZAwBoQHuk6T2b40WuBm7m+uf/M383BQS6H/uajJMKpmh4OZxSKEBHxOjsIvwAUAGYqaLadh194A87EwIZH9u1dhMeJe9UKMAhhIwnOVAAIMBu6sHkFplcm8gYW1vdW50IHRlc3S5L3Vn");
}

TEST(AeternitySigner, SignTxWithZeroNonce) {
std::string sender_id = "ak_2p5878zbFhxnrm7meL7TmqwtvBaqcBddyp5eGzZbovZ5FeVfcw";
std::string recipient_id = "ak_Egp9yVdpxmvAfQ7vsXGvpnyfNq71msbdUpkMNYGTeTe8kPL3v";
uint256_t amount = 3369980000000000000;
uint256_t fee = 20000000000000;
std::string payload = "Zero nonce test";
uint64_t ttl = 113579;
uint64_t nonce = 0;

auto transaction = Transaction(sender_id, recipient_id, amount, fee, payload, ttl, nonce);
auto privateKey = PrivateKey(parse_hex("4646464646464646464646464646464646464646464646464646464646464646"));

auto result = Signer::sign(privateKey, transaction);
EXPECT_EQ(result.signature(), "sg_MaJc4ptSUhq5kH6mArszDAvu4f7PejyuhmgM6U8GEr8bRUTaSFbdFPx4C6FEYA5v5Lgwu9EToaWnHgR2xkqZ9JjHnaBpA");
EXPECT_EQ(result.encoded(), "tx_+LULAfhCuECdQsgcE8bp+9CANdasxkt5gxfjBSI1ztyPl1aNJbm+MwUvE7Lu/qvAkHijfe+Eui2zrqhZRYc5mblRa+oLOIIEuG34awwBoQHuk6T2b40WuBm7m+uf/M383BQS6H/uajJMKpmh4OZxSKEBHxOjsIvwAUAGYqaLadh194A87EwIZH9u1dhMeJe9UKOILsSS9IArwACGEjCc5UAAgwG7qwCPWmVybyBub25jZSB0ZXN0piWfFA==");
}


32 changes: 32 additions & 0 deletions tests/Aeternity/TransactionTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,35 @@ TEST(AeternityTransaction, EncodeRlp) {
ASSERT_EQ(encodedTxHex, "f85f0c01a101cea7ade470c9f99d9d4e400880a86f1d49bb444b62f11a9ebb64bbcfeb73fef3a1011f13a3b08bf001400662a68b69d875f7803cec4c08647f6ed5d84c7897bd50a30a8612309ce5400083014345318b48656c6c6f20576f726c64");
}

TEST(AeternityTransaction, EncodeRlpWithZeroAmount) {
std::string sender_id = "ak_2a1j2Mk9YSmC1gioUq4PWRm3bsv887MbuRVwyv4KaUGoR1eiKi";
std::string recipient_id = "ak_Egp9yVdpxmvAfQ7vsXGvpnyfNq71msbdUpkMNYGTeTe8kPL3v";
uint64_t amount = 0;
uint64_t fee = 2e13;
std::string payload = "Hello World";
uint64_t ttl = 82757;
uint64_t nonce = 49;

auto tx = Transaction(sender_id, recipient_id, amount, fee, payload, ttl, nonce);
auto encodedTx = tx.encode();
auto encodedTxHex = hex(encodedTx);

ASSERT_EQ(encodedTxHex, "f85f0c01a101cea7ade470c9f99d9d4e400880a86f1d49bb444b62f11a9ebb64bbcfeb73fef3a1011f13a3b08bf001400662a68b69d875f7803cec4c08647f6ed5d84c7897bd50a3008612309ce5400083014345318b48656c6c6f20576f726c64");
}

TEST(AeternityTransaction, EncodeRlpWithZeroTtl) {
std::string sender_id = "ak_2a1j2Mk9YSmC1gioUq4PWRm3bsv887MbuRVwyv4KaUGoR1eiKi";
std::string recipient_id = "ak_Egp9yVdpxmvAfQ7vsXGvpnyfNq71msbdUpkMNYGTeTe8kPL3v";
uint64_t amount = 10;
uint64_t fee = 2e13;
std::string payload = "Hello World";
uint64_t ttl = 0;
uint64_t nonce = 49;

auto tx = Transaction(sender_id, recipient_id, amount, fee, payload, ttl, nonce);
auto encodedTx = tx.encode();
auto encodedTxHex = hex(encodedTx);

ASSERT_EQ(encodedTxHex, "f85c0c01a101cea7ade470c9f99d9d4e400880a86f1d49bb444b62f11a9ebb64bbcfeb73fef3a1011f13a3b08bf001400662a68b69d875f7803cec4c08647f6ed5d84c7897bd50a30a8612309ce5400000318b48656c6c6f20576f726c64");
}

1 change: 1 addition & 0 deletions tests/CoinAddressValidationTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ TEST(Coin, ValidateAddressWaves) {
}

TEST(Coin, ValidateAddressAeternity) {
EXPECT_TRUE(validateAddress(TWCoinTypeAeternity, "ak_22ZPJTLbSDpAUfJbBJvqvXFuFe2RoP1ZEd7K9qaHJWF92MgnWm"));
EXPECT_TRUE(validateAddress(TWCoinTypeAeternity, "ak_11111111111111111111111111111111273Yts"));

// wrong checksum
Expand Down
Loading

0 comments on commit 6359763

Please sign in to comment.