Skip to content

Commit

Permalink
Add additional key tests (#2401)
Browse files Browse the repository at this point in the history
* Add additional key tests

* lint: add locale exceptions for test
  • Loading branch information
Bushstar authored Sep 4, 2023
1 parent edf134e commit 0e0a5fe
Show file tree
Hide file tree
Showing 6 changed files with 299 additions and 27 deletions.
18 changes: 13 additions & 5 deletions src/masternodes/rpc_accounts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ UniValue getaccount(const JSONRPCRequest& request) {
if (auto res = GetRPCResultCache().TryGet(request)) return *res;

// decode owner
const auto reqOwner = DecodeScript(request.params[0].get_str());
const auto reqOwner = GetScriptForDestination(DecodeDestination(request.params[0].get_str()));

// parse pagination
size_t limit = 100;
Expand Down Expand Up @@ -2057,8 +2057,12 @@ UniValue transferdomain(const JSONRPCRequest& request) {

CTransferDomainItem src, dst;

if (!srcObj["address"].isNull())
src.address = DecodeScript(srcObj["address"].getValStr());
if (!srcObj["address"].isNull()) {
const auto dest = DecodeDestination(srcObj["address"].getValStr());
if (!IsValidDestination(dest))
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid src address provided");
src.address = GetScriptForDestination(dest);
}
else
throw JSONRPCError(RPC_INVALID_PARAMETER,"Invalid parameters, src argument \"address\" must not be null");

Expand Down Expand Up @@ -2088,8 +2092,12 @@ UniValue transferdomain(const JSONRPCRequest& request) {
if (!srcObj["data"].isNull())
src.data.assign(srcObj["data"].getValStr().begin(), srcObj["data"].getValStr().end());

if (!dstObj["address"].isNull())
dst.address = DecodeScript(dstObj["address"].getValStr());
if (!dstObj["address"].isNull()) {
const auto dest = DecodeDestination(dstObj["address"].getValStr());
if (!IsValidDestination(dest))
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid dst address provided");
dst.address = GetScriptForDestination(dest);
}
else
throw JSONRPCError(RPC_INVALID_PARAMETER,"Invalid parameters, dst argument \"address\" must not be null");

Expand Down
4 changes: 3 additions & 1 deletion src/rpc/rawtransaction_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ ResVal<CTokenAmount> GuessTokenAmount(interfaces::Chain const & chain, std::stri
}


// decodes either base58/bech32 address, or a hex format
// Decodes either base58/bech32 address, or a hex format. Legacy function, should
// use DecodeScript(DecodeDestination(str)) to ensure proper decoding of address
// to script to include erc55 address support.
CScript DecodeScript(std::string const& str)
{
if (IsHex(str)) {
Expand Down
277 changes: 268 additions & 9 deletions src/test/key_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <key.h>

#include <bech32.h>
#include <key_io.h>
#include <uint256.h>
#include <util/system.h>
Expand All @@ -19,17 +20,31 @@ static const std::string strSecret1 = "5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHf
static const std::string strSecret2 = "5KC4ejrDjv152FGwP386VD1i2NYc5KkfSMyv1nGy1VGDxGHqVY3";
static const std::string strSecret1C = "Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw";
static const std::string strSecret2C = "L3Hq7a8FEQwJkW1M2GNKDW28546Vp5miewcCzSqUD9kCAXrJdS3g";
static const std::string addr1 = "8eLhZJqPrKuFmBonk7tK3Tma6oyRvJM4Tz";
static const std::string addr2 = "8VApoBSS8rRKiRpSchh5JjYDNLrvyXEYgJ";
static const std::string addr1C = "8ctAamF4jdX6NzoTk5So1qXUBc4CxovyK9";
static const std::string addr2C = "8SWakFLXnSsHi5g5mxtSzbsr1T68JmXMdR";

// public key hash addresses
static const std::string pkh_addr1 = "8eLhZJqPrKuFmBonk7tK3Tma6oyRvJM4Tz";
static const std::string pkh_addr2 = "8VApoBSS8rRKiRpSchh5JjYDNLrvyXEYgJ";
static const std::string pkh_addr1C = "8ctAamF4jdX6NzoTk5So1qXUBc4CxovyK9";
static const std::string pkh_addr2C = "8SWakFLXnSsHi5g5mxtSzbsr1T68JmXMdR";

// witness public key hash addresses
static const std::string wpkh_addr1 = "df1qluvhk989q245ruau3n95339t4j02kddu2vqwve";
static const std::string wpkh_addr2 = "df1qn2prk6v0w78vay9sjnwr7y4gra0rcv69f5qxqz";
static const std::string wpkh_addr1C = "df1qauw2aajwu832l7rhkl5wjufacfdj9z0jquwv3z";
static const std::string wpkh_addr2C = "df1q04t8rax7tc7s2jzeuphjpyvuc0vgygsz3drcsg";

// erc55 addresses
static const std::string erc55_addr1 = "0x482e975Ee029d6d268CC1dCce529748a06A46AAc";
static const std::string erc55_addr2 = "0x43162a466BD5891dfBf7c438b0c35F0144690D26";
static const std::string erc55_addr1C = "0x2D586e4Dec0798F728b626a4f134a3728772a8E5";
static const std::string erc55_addr2C = "0x83bB997178Cd7F6876620096EFADB18a712eDdca";

static const std::string strAddressBad = "1HV9Lc3sNHZxwj4Zk6fB38tEmBryq2cBiF";


BOOST_FIXTURE_TEST_SUITE(key_tests, BasicTestingSetup)

BOOST_AUTO_TEST_CASE(key_test1)
BOOST_AUTO_TEST_CASE(key_test_1)
{
CKey key1 = DecodeSecret(strSecret1);
BOOST_CHECK(key1.IsValid() && !key1.IsCompressed());
Expand Down Expand Up @@ -67,10 +82,10 @@ BOOST_AUTO_TEST_CASE(key_test1)
BOOST_CHECK(!key2C.VerifyPubKey(pubkey2));
BOOST_CHECK(key2C.VerifyPubKey(pubkey2C));

BOOST_CHECK(DecodeDestination(addr1) == CTxDestination(PKHash(pubkey1)));
BOOST_CHECK(DecodeDestination(addr2) == CTxDestination(PKHash(pubkey2)));
BOOST_CHECK(DecodeDestination(addr1C) == CTxDestination(PKHash(pubkey1C)));
BOOST_CHECK(DecodeDestination(addr2C) == CTxDestination(PKHash(pubkey2C)));
BOOST_CHECK(DecodeDestination(pkh_addr1) == CTxDestination(PKHash(pubkey1)));
BOOST_CHECK(DecodeDestination(pkh_addr2) == CTxDestination(PKHash(pubkey2)));
BOOST_CHECK(DecodeDestination(pkh_addr1C) == CTxDestination(PKHash(pubkey1C)));
BOOST_CHECK(DecodeDestination(pkh_addr2C) == CTxDestination(PKHash(pubkey2C)));

for (int n=0; n<16; n++)
{
Expand Down Expand Up @@ -219,4 +234,248 @@ BOOST_AUTO_TEST_CASE(key_key_negation)
BOOST_CHECK(key.GetPubKey().data()[0] == 0x03);
}

BOOST_AUTO_TEST_CASE(pkh_key_test)
{
CKey key1 = DecodeSecret(strSecret1);
BOOST_CHECK(key1.IsValid() && !key1.IsCompressed());
CKey key2 = DecodeSecret(strSecret2);
BOOST_CHECK(key2.IsValid() && !key2.IsCompressed());
CKey key1C = DecodeSecret(strSecret1C);
BOOST_CHECK(key1C.IsValid() && key1C.IsCompressed());
CKey key2C = DecodeSecret(strSecret2C);
BOOST_CHECK(key2C.IsValid() && key2C.IsCompressed());
CKey bad_key = DecodeSecret(strAddressBad);
BOOST_CHECK(!bad_key.IsValid());

CPubKey pubkey1 = key1. GetPubKey();
CPubKey pubkey2 = key2. GetPubKey();
CPubKey pubkey1C = key1C.GetPubKey();
CPubKey pubkey2C = key2C.GetPubKey();

BOOST_CHECK(key1.VerifyPubKey(pubkey1));
BOOST_CHECK(!key1.VerifyPubKey(pubkey1C));
BOOST_CHECK(!key1.VerifyPubKey(pubkey2));
BOOST_CHECK(!key1.VerifyPubKey(pubkey2C));

BOOST_CHECK(!key1C.VerifyPubKey(pubkey1));
BOOST_CHECK(key1C.VerifyPubKey(pubkey1C));
BOOST_CHECK(!key1C.VerifyPubKey(pubkey2));
BOOST_CHECK(!key1C.VerifyPubKey(pubkey2C));

BOOST_CHECK(!key2.VerifyPubKey(pubkey1));
BOOST_CHECK(!key2.VerifyPubKey(pubkey1C));
BOOST_CHECK(key2.VerifyPubKey(pubkey2));
BOOST_CHECK(!key2.VerifyPubKey(pubkey2C));

BOOST_CHECK(!key2C.VerifyPubKey(pubkey1));
BOOST_CHECK(!key2C.VerifyPubKey(pubkey1C));
BOOST_CHECK(!key2C.VerifyPubKey(pubkey2));
BOOST_CHECK(key2C.VerifyPubKey(pubkey2C));

BOOST_CHECK(DecodeDestination(pkh_addr1) == CTxDestination(PKHash(pubkey1)));
BOOST_CHECK(DecodeDestination(pkh_addr2) == CTxDestination(PKHash(pubkey2)));
BOOST_CHECK(DecodeDestination(pkh_addr1C) == CTxDestination(PKHash(pubkey1C)));
BOOST_CHECK(DecodeDestination(pkh_addr2C) == CTxDestination(PKHash(pubkey2C)));

BOOST_CHECK(pkh_addr1 == EncodeDestination(CTxDestination(PKHash(pubkey1))));
BOOST_CHECK(pkh_addr2 == EncodeDestination(CTxDestination(PKHash(pubkey2))));
BOOST_CHECK(pkh_addr1C == EncodeDestination(CTxDestination(PKHash(pubkey1C))));
BOOST_CHECK(pkh_addr2C == EncodeDestination(CTxDestination(PKHash(pubkey2C))));

// Test script to destination conversions
CScript pkh_addr1_script = GetScriptForDestination(DecodeDestination(pkh_addr1));
CScript pkh_addr2_script = GetScriptForDestination(DecodeDestination(pkh_addr2));
CScript pkh_addr1C_script = GetScriptForDestination(DecodeDestination(pkh_addr1C));
CScript pkh_addr2C_script = GetScriptForDestination(DecodeDestination(pkh_addr2C));

CTxDestination pkh_addr1_script_dest;
CTxDestination pkh_addr2_script_dest;
CTxDestination pkh_addr1C_script_dest;
CTxDestination pkh_addr2C_script_dest;
ExtractDestination(pkh_addr1_script, pkh_addr1_script_dest);
ExtractDestination(pkh_addr2_script, pkh_addr2_script_dest);
ExtractDestination(pkh_addr1C_script, pkh_addr1C_script_dest);
ExtractDestination(pkh_addr2C_script, pkh_addr2C_script_dest);

BOOST_CHECK(pkh_addr1 == EncodeDestination(pkh_addr1_script_dest));
BOOST_CHECK(pkh_addr2 == EncodeDestination(pkh_addr2_script_dest));
BOOST_CHECK(pkh_addr1C == EncodeDestination(pkh_addr1C_script_dest));
BOOST_CHECK(pkh_addr2C == EncodeDestination(pkh_addr2C_script_dest));
}

BOOST_AUTO_TEST_CASE(serialised_address_from_block_test)
{
// Addresses
auto bech32 = "bcrt1qta8meuczw0mhqupzjl5wplz47xajz0dn0wxxr8";
auto eth = "0x9b8a4af42140d8a4c153a822f02571a1dd037e89";

// CKeyIDs taken from serialised block
auto bech32Hex = "5f4fbcf30273f770702297e8e0fc55f1bb213db3";
auto ethHex = "897e03dda17125f022a853c1a4d84021f44a8a9b";

// Encode Bech32
auto bech32Vec = ParseHex(bech32Hex);
std::vector<unsigned char> data = {0};
data.reserve(33);
ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, bech32Vec.begin(), bech32Vec.end());
auto bech32Encoded = bech32::Encode("bcrt", data);

// Encode Eth
auto ethVec = ParseHex(ethHex);
auto ethID = HexStr(ethVec.rbegin(), ethVec.rend());
std::vector<uint8_t> ethOutput, ethInput(ethID.begin(), ethID.end());
sha3_256_safe(ethInput, ethOutput);
auto hashedAddress = HexStr(ethOutput);
std::string ethEncoded = "0x";
for (size_t i{}; i < ethID.size(); ++i) {
if (std::isdigit(ethID[i]) || hashedAddress[i] < '8') {
ethEncoded += ethID[i];
} else {
ethEncoded += std::toupper(ethID[i]);
}
}

// Check results match
BOOST_CHECK_EQUAL(bech32, bech32Encoded);
BOOST_CHECK_EQUAL(eth, ethEncoded);
}

BOOST_AUTO_TEST_CASE(wpkh_key_test)
{
CKey key1 = DecodeSecret(strSecret1);
BOOST_CHECK(key1.IsValid() && !key1.IsCompressed());
CKey key2 = DecodeSecret(strSecret2);
BOOST_CHECK(key2.IsValid() && !key2.IsCompressed());
CKey key1C = DecodeSecret(strSecret1C);
BOOST_CHECK(key1C.IsValid() && key1C.IsCompressed());
CKey key2C = DecodeSecret(strSecret2C);
BOOST_CHECK(key2C.IsValid() && key2C.IsCompressed());
CKey bad_key = DecodeSecret(strAddressBad);
BOOST_CHECK(!bad_key.IsValid());

CPubKey pubkey1 = key1. GetPubKey();
CPubKey pubkey2 = key2. GetPubKey();
CPubKey pubkey1C = key1C.GetPubKey();
CPubKey pubkey2C = key2C.GetPubKey();

BOOST_CHECK(key1.VerifyPubKey(pubkey1));
BOOST_CHECK(!key1.VerifyPubKey(pubkey1C));
BOOST_CHECK(!key1.VerifyPubKey(pubkey2));
BOOST_CHECK(!key1.VerifyPubKey(pubkey2C));

BOOST_CHECK(!key1C.VerifyPubKey(pubkey1));
BOOST_CHECK(key1C.VerifyPubKey(pubkey1C));
BOOST_CHECK(!key1C.VerifyPubKey(pubkey2));
BOOST_CHECK(!key1C.VerifyPubKey(pubkey2C));

BOOST_CHECK(!key2.VerifyPubKey(pubkey1));
BOOST_CHECK(!key2.VerifyPubKey(pubkey1C));
BOOST_CHECK(key2.VerifyPubKey(pubkey2));
BOOST_CHECK(!key2.VerifyPubKey(pubkey2C));

BOOST_CHECK(!key2C.VerifyPubKey(pubkey1));
BOOST_CHECK(!key2C.VerifyPubKey(pubkey1C));
BOOST_CHECK(!key2C.VerifyPubKey(pubkey2));
BOOST_CHECK(key2C.VerifyPubKey(pubkey2C));

BOOST_CHECK(DecodeDestination(wpkh_addr1) == CTxDestination(WitnessV0KeyHash(pubkey1)));
BOOST_CHECK(DecodeDestination(wpkh_addr2) == CTxDestination(WitnessV0KeyHash(pubkey2)));
BOOST_CHECK(DecodeDestination(wpkh_addr1C) == CTxDestination(WitnessV0KeyHash(pubkey1C)));
BOOST_CHECK(DecodeDestination(wpkh_addr2C) == CTxDestination(WitnessV0KeyHash(pubkey2C)));

BOOST_CHECK(wpkh_addr1 == EncodeDestination(CTxDestination(WitnessV0KeyHash(pubkey1))));
BOOST_CHECK(wpkh_addr2 == EncodeDestination(CTxDestination(WitnessV0KeyHash(pubkey2))));
BOOST_CHECK(wpkh_addr1C == EncodeDestination(CTxDestination(WitnessV0KeyHash(pubkey1C))));
BOOST_CHECK(wpkh_addr2C == EncodeDestination(CTxDestination(WitnessV0KeyHash(pubkey2C))));

// Test script to destination conversions
CScript wpkh_addr1_script = GetScriptForDestination(DecodeDestination(wpkh_addr1));
CScript wpkh_addr2_script = GetScriptForDestination(DecodeDestination(wpkh_addr2));
CScript wpkh_addr1C_script = GetScriptForDestination(DecodeDestination(wpkh_addr1C));
CScript wpkh_addr2C_script = GetScriptForDestination(DecodeDestination(wpkh_addr2C));

CTxDestination wpkh_addr1_script_dest;
CTxDestination wpkh_addr2_script_dest;
CTxDestination wpkh_addr1C_script_dest;
CTxDestination wpkh_addr2C_script_dest;
ExtractDestination(wpkh_addr1_script, wpkh_addr1_script_dest);
ExtractDestination(wpkh_addr2_script, wpkh_addr2_script_dest);
ExtractDestination(wpkh_addr1C_script, wpkh_addr1C_script_dest);
ExtractDestination(wpkh_addr2C_script, wpkh_addr2C_script_dest);

BOOST_CHECK(wpkh_addr1 == EncodeDestination(wpkh_addr1_script_dest));
BOOST_CHECK(wpkh_addr2 == EncodeDestination(wpkh_addr2_script_dest));
BOOST_CHECK(wpkh_addr1C == EncodeDestination(wpkh_addr1C_script_dest));
BOOST_CHECK(wpkh_addr2C == EncodeDestination(wpkh_addr2C_script_dest));
}

BOOST_AUTO_TEST_CASE(erc55_key_test)
{
CKey key1 = DecodeSecret(strSecret1);
BOOST_CHECK(key1.IsValid() && !key1.IsCompressed());
CKey key2 = DecodeSecret(strSecret2);
BOOST_CHECK(key2.IsValid() && !key2.IsCompressed());
CKey key1C = DecodeSecret(strSecret1C);
BOOST_CHECK(key1C.IsValid() && key1C.IsCompressed());
CKey key2C = DecodeSecret(strSecret2C);
BOOST_CHECK(key2C.IsValid() && key2C.IsCompressed());
CKey bad_key = DecodeSecret(strAddressBad);
BOOST_CHECK(!bad_key.IsValid());

CPubKey pubkey1 = key1. GetPubKey();
CPubKey pubkey2 = key2. GetPubKey();
CPubKey pubkey1C = key1C.GetPubKey();
CPubKey pubkey2C = key2C.GetPubKey();

BOOST_CHECK(key1.VerifyPubKey(pubkey1));
BOOST_CHECK(!key1.VerifyPubKey(pubkey1C));
BOOST_CHECK(!key1.VerifyPubKey(pubkey2));
BOOST_CHECK(!key1.VerifyPubKey(pubkey2C));

BOOST_CHECK(!key1C.VerifyPubKey(pubkey1));
BOOST_CHECK(key1C.VerifyPubKey(pubkey1C));
BOOST_CHECK(!key1C.VerifyPubKey(pubkey2));
BOOST_CHECK(!key1C.VerifyPubKey(pubkey2C));

BOOST_CHECK(!key2.VerifyPubKey(pubkey1));
BOOST_CHECK(!key2.VerifyPubKey(pubkey1C));
BOOST_CHECK(key2.VerifyPubKey(pubkey2));
BOOST_CHECK(!key2.VerifyPubKey(pubkey2C));

BOOST_CHECK(!key2C.VerifyPubKey(pubkey1));
BOOST_CHECK(!key2C.VerifyPubKey(pubkey1C));
BOOST_CHECK(!key2C.VerifyPubKey(pubkey2));
BOOST_CHECK(key2C.VerifyPubKey(pubkey2C));

BOOST_CHECK(DecodeDestination(erc55_addr1) == CTxDestination(WitnessV16EthHash(pubkey1)));
BOOST_CHECK(DecodeDestination(erc55_addr2) == CTxDestination(WitnessV16EthHash(pubkey2)));
BOOST_CHECK(DecodeDestination(erc55_addr1C) == CTxDestination(WitnessV16EthHash(pubkey1C)));
BOOST_CHECK(DecodeDestination(erc55_addr2C) == CTxDestination(WitnessV16EthHash(pubkey2C)));

BOOST_CHECK(erc55_addr1 == EncodeDestination(CTxDestination(WitnessV16EthHash(pubkey1))));
BOOST_CHECK(erc55_addr2 == EncodeDestination(CTxDestination(WitnessV16EthHash(pubkey2))));
BOOST_CHECK(erc55_addr1C == EncodeDestination(CTxDestination(WitnessV16EthHash(pubkey1C))));
BOOST_CHECK(erc55_addr2C == EncodeDestination(CTxDestination(WitnessV16EthHash(pubkey2C))));

// Test script to destination conversions
CScript erc55_addr1_script = GetScriptForDestination(DecodeDestination(erc55_addr1));
CScript erc55_addr2_script = GetScriptForDestination(DecodeDestination(erc55_addr2));
CScript erc55_addr1C_script = GetScriptForDestination(DecodeDestination(erc55_addr1C));
CScript erc55_addr2C_script = GetScriptForDestination(DecodeDestination(erc55_addr2C));

CTxDestination erc55_addr1_script_dest;
CTxDestination erc55_addr2_script_dest;
CTxDestination erc55_addr1C_script_dest;
CTxDestination erc55_addr2C_script_dest;
ExtractDestination(erc55_addr1_script, erc55_addr1_script_dest);
ExtractDestination(erc55_addr2_script, erc55_addr2_script_dest);
ExtractDestination(erc55_addr1C_script, erc55_addr1C_script_dest);
ExtractDestination(erc55_addr2C_script, erc55_addr2C_script_dest);

BOOST_CHECK(erc55_addr1 == EncodeDestination(erc55_addr1_script_dest));
BOOST_CHECK(erc55_addr2 == EncodeDestination(erc55_addr2_script_dest));
BOOST_CHECK(erc55_addr1C == EncodeDestination(erc55_addr1C_script_dest));
BOOST_CHECK(erc55_addr2C == EncodeDestination(erc55_addr2C_script_dest));
}

BOOST_AUTO_TEST_SUITE_END()
17 changes: 9 additions & 8 deletions test/functional/feature_evm.py
Original file line number Diff line number Diff line change
Expand Up @@ -980,14 +980,15 @@ def validate_xvm_coinbase(self):
assert_equal(opreturn_priority_fee_amount, self.miner_fee)

# Check EVM beneficiary address
opreturn_miner_keyid = coinbase_xvm["msg"]["evm"]["beneficiary"][2:]
miner_eth_address = self.nodes[0].addressmap(
self.nodes[0].get_genesis_keys().operatorAuthAddress, 1
)
miner_eth_keyid = self.nodes[0].getaddressinfo(
miner_eth_address["format"]["erc55"]
)["witness_program"]
assert_equal(opreturn_miner_keyid, miner_eth_keyid)
opreturn_miner_address = coinbase_xvm["msg"]["evm"]["beneficiary"][2:]
miner_eth_address = (
self.nodes[0]
.addressmap(self.nodes[0].get_genesis_keys().operatorAuthAddress, 1)[
"format"
]["erc55"][2:]
.lower()
)
assert_equal(opreturn_miner_address, miner_eth_address)

def evm_rollback(self):
# Test rollback of EVM TX
Expand Down
Loading

0 comments on commit 0e0a5fe

Please sign in to comment.