Skip to content

Commit

Permalink
Split addressmap from vmmap into wallet RPCs (#2232)
Browse files Browse the repository at this point in the history
* Split vm address map from vmmap

* Move vmaddressmap to addressmap and in wallet RPCs

---------

Co-authored-by: Prasanna Loganathar <[email protected]>
  • Loading branch information
Mixa84 and prasannavl authored Jul 26, 2023
1 parent 1a64d39 commit 9a6e2fb
Show file tree
Hide file tree
Showing 10 changed files with 205 additions and 58 deletions.
54 changes: 11 additions & 43 deletions src/masternodes/rpc_evm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@

enum class VMDomainRPCMapType {
Auto,
AddressDVMToEVM,
AddressEVMToDVM,
TxHashDVMToEVM,
TxHashEVMToEVM,
BlockHashDVMToEVM,
Expand All @@ -17,7 +15,7 @@ enum class VMDomainRPCMapType {
BlockNumberEVMToDVM,
};

static int VMDomainRPCMapTypeCount = 9;
static int VMDomainRPCMapTypeCount = 7;

enum class VMDomainIndexType { BlockHash, TxHash };

Expand Down Expand Up @@ -192,7 +190,6 @@ UniValue handleMapBlockNumberDVMToEVMRequest(const std::string &input) {
}

UniValue vmmap(const JSONRPCRequest &request) {
auto pwallet = GetWallet(request);
RPCHelpMan{
"vmmap",
"Give the equivalent of an address, blockhash or transaction from EVM to DVM\n",
Expand All @@ -201,16 +198,14 @@ UniValue vmmap(const JSONRPCRequest &request) {
RPCArg::Type::NUM,
RPCArg::Optional::NO,
"Map types: \n\
1 - Address format: DFI -> ETH \n\
2 - Address format: ETH -> DFI \n\
3 - Tx Hash: DFI -> EVM \n\
4 - Tx Hash: EVM -> DFI \n\
5 - Block Hash: DFI -> EVM \n\
6 - Block Hash: EVM -> DFI \n\
7 - Block Number: DFI -> EVM \n\
8 - Block Number: EVM -> DFI"}},
1 - Tx Hash: DFI -> EVM \n\
2 - Tx Hash: EVM -> DFI \n\
3 - Block Hash: DFI -> EVM \n\
4 - Block Hash: EVM -> DFI \n\
5 - Block Number: DFI -> EVM \n\
6 - Block Number: EVM -> DFI"}},
RPCResult{"\"input\" (string) The hex-encoded string for address, block or transaction\n"},
RPCExamples{HelpExampleCli("vmmap", R"('"<hex>"' 1)")},
RPCExamples{HelpExampleCli("vmmap", R"('"<hash>"' 1)")},
}
.Check(request);

Expand All @@ -230,33 +225,6 @@ UniValue vmmap(const JSONRPCRequest &request) {
throwInvalidParam();
}
const auto type = static_cast<VMDomainRPCMapType>(request.params[1].get_int());
switch (type) {
case VMDomainRPCMapType::AddressDVMToEVM: {
CTxDestination dest = DecodeDestination(input);
if (dest.index() != WitV0KeyHashType && dest.index() != PKHashType) {
throwInvalidParam();
}
CPubKey key = AddrToPubKey(pwallet, input);
if (key.IsCompressed()) {
key.Decompress();
}
return EncodeDestination(WitnessV16EthHash(key));
}
case VMDomainRPCMapType::AddressEVMToDVM: {
CTxDestination dest = DecodeDestination(input);
if (dest.index() != WitV16KeyEthHashType) {
throwInvalidParam();
}
CPubKey key = AddrToPubKey(pwallet, input);
if (!key.IsCompressed()) {
key.Compress();
}
return EncodeDestination(WitnessV0KeyHash(key));
}
default:
break;
}

LOCK(cs_main);

ResVal res = ResVal<uint256>(uint256{}, Res::Ok());
Expand Down Expand Up @@ -345,9 +313,9 @@ UniValue logvmmaps(const JSONRPCRequest &request) {
static const CRPCCommand commands[] = {
// category name actor (function) params
// --------------- ---------------------- --------------------- ----------
{"evm", "evmtx", &evmtx, {"from", "nonce", "gasPrice", "gasLimit", "to", "value", "data"}},
{"evm", "vmmap", &vmmap, {"input", "type"} },
{"evm", "logvmmaps", &logvmmaps, {"type"} },
{"evm", "evmtx", &evmtx, {"from", "nonce", "gasPrice", "gasLimit", "to", "value", "data"}},
{"evm", "vmmap", &vmmap, {"input", "type"} },
{"evm", "logvmmaps", &logvmmaps, {"type"} },
};

void RegisterEVMRPCCommands(CRPCTable &tableRPC) {
Expand Down
1 change: 1 addition & 0 deletions src/rpc/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "evmtx", 5, "value" },
{ "vmmap", 1, "type"},
{ "logvmmaps", 0, "type"},
{ "addressmap", 1, "type"},
};
// clang-format on

Expand Down
65 changes: 65 additions & 0 deletions src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4236,6 +4236,70 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
return result;
}

enum class AddressConversionType {
Auto,
DVMToEVMAddress,
EVMToDVMAddress,
};

static int AddressConversionTypeCount = 3;

UniValue addressmap(const JSONRPCRequest &request) {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();

RPCHelpMan{
"addressmap",
"Give the equivalent of an address from EVM to DVM and versa\n",
{
{"input", RPCArg::Type::STR, RPCArg::Optional::NO, "DVM address or EVM address"},
{"type", RPCArg::Type::NUM, RPCArg::Optional::NO, "Map types: \n\
1 - Address format: DFI -> ETH \n\
2 - Address format: ETH -> DFI \n"}
},
RPCResult{"\"input\" (string) The hex-encoded string for address, block or transaction\n"},
RPCExamples{HelpExampleCli("addressmap", R"('"<address>"' 1)")},
}
.Check(request);

auto throwInvalidParam = []() { throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid type parameter")); };

const std::string input = request.params[0].get_str();

const int typeInt = request.params[1].get_int();
if (typeInt < 0 || typeInt >= AddressConversionTypeCount) {
throwInvalidParam();
}
const auto type = static_cast<AddressConversionType>(request.params[1].get_int());
switch (type) {
case AddressConversionType::DVMToEVMAddress: {
CTxDestination dest = DecodeDestination(input);
if (dest.index() != WitV0KeyHashType && dest.index() != PKHashType) {
throwInvalidParam();
}
CPubKey key = AddrToPubKey(pwallet, input);
if (key.IsCompressed()) {
key.Decompress();
}
return EncodeDestination(WitnessV16EthHash(key));
}
case AddressConversionType::EVMToDVMAddress: {
CTxDestination dest = DecodeDestination(input);
if (dest.index() != WitV16KeyEthHashType) {
throwInvalidParam();
}
CPubKey key = AddrToPubKey(pwallet, input);
if (!key.IsCompressed()) {
key.Compress();
}
return EncodeDestination(WitnessV0KeyHash(key));
}
default:
throw JSONRPCError(RPC_INVALID_REQUEST, "Invalid address type passed");
break;
}
}

UniValue abortrescan(const JSONRPCRequest& request); // in rpcdump.cpp
UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp
UniValue importprivkey(const JSONRPCRequest& request);
Expand All @@ -4255,6 +4319,7 @@ static const CRPCCommand commands[] =
{ "wallet", "abandontransaction", &abandontransaction, {"txid"} },
{ "wallet", "abortrescan", &abortrescan, {} },
{ "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","label","address_type"} },
{ "wallet", "addressmap", &addressmap, {"input", "type"} },
{ "wallet", "backupwallet", &backupwallet, {"destination"} },
{ "wallet", "bumpfee", &bumpfee, {"txid", "options"} },
{ "wallet", "createwallet", &createwallet, {"wallet_name", "disable_private_keys", "blank", "passphrase", "avoid_reuse"} },
Expand Down
114 changes: 114 additions & 0 deletions test/functional/feature_address_map.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#!/usr/bin/env python3
# Copyright (c) 2014-2019 The Bitcoin Core developers
# Copyright (c) DeFi Blockchain Developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
"""Test addressmap behaviour"""

from test_framework.test_framework import DefiTestFramework
from test_framework.util import (
assert_equal,
assert_raises_rpc_error
)

class AddressConversionType:
Auto = 0
DVMToEVMAddress = 1
EVMToDVMAddress = 2

class addressmapTests(DefiTestFramework):
def set_test_params(self):
self.num_nodes = 2
self.setup_clean_chain = True
self.extra_args = [
['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-fortcanningepilogueheight=96', '-grandcentralheight=101', '-nextnetworkupgradeheight=105', '-changiintermediateheight=105', '-changiintermediate2height=105', '-changiintermediate3height=105', '-changiintermediate4height=105', '-subsidytest=1', '-txindex=1'],
['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-fortcanningepilogueheight=96', '-grandcentralheight=101', '-nextnetworkupgradeheight=105', '-changiintermediateheight=105', '-changiintermediate2height=105', '-changiintermediate3height=105', '-changiintermediate4height=105', '-subsidytest=1', '-txindex=1'],
]

def setup(self):
self.address = self.nodes[0].get_genesis_keys().ownerAuthAddress
self.ethAddress = '0x9b8a4af42140d8a4c153a822f02571a1dd037e89'
self.toAddress = '0x6c34cbb9219d8caa428835d2073e8ec88ba0a110'
self.nodes[0].importprivkey('af990cc3ba17e776f7f57fcc59942a82846d75833fa17d2ba59ce6858d886e23') # ethAddress
self.nodes[0].importprivkey('17b8cb134958b3d8422b6c43b0732fcdb8c713b524df2d45de12f0c7e214ba35') # toAddress

# Generate chain
self.nodes[0].generate(101)
assert_raises_rpc_error(-32600, "called before NextNetworkUpgrade height", self.nodes[0].evmtx, self.ethAddress, 0, 21, 21000, self.toAddress, 0.1)

# Move to fork height
self.nodes[0].generate(4)

self.nodes[0].getbalance()
self.nodes[0].utxostoaccount({self.address: "201@DFI"})
self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/feature/evm': 'true', 'v0/params/feature/transferdomain': 'true', 'v0/transferdomain/allowed/dvm-evm': 'true'}})
self.nodes[0].generate(1)
self.start_block_height = self.nodes[0].getblockcount()

def addressmap_address_basics_manual_import(self):
self.rollback_to(self.start_block_height)
# Import both keys for now.
priv_keys = [
["cNoUVyyacpVBpotBGxrnM5XXekdqV8qgnowVQfgCvDWVU9jn4gUz", "2468918553ca24474efea1e6a3641a1302bd643d15c13a6dbe89b8da38c90b3c"],
["cPaTadxsWhzHNgi2hAiFXXnw7foEGXBME75s27CEGFeS8S3pYf8j", "3b8ccde96d9c78c6cf248ffcb9ed89ba8327b8c994600ca391b38f5deffa15ca"],
["cSu1eq6MKxZ2exooiXEwC7jA4W7Gd3YyfDL8BWQCm8abaDKrnDkr", "9e9b4756952999af30a62ebe4f8bcd12ed251d820e5d3c8cee550685693f2688"],
]
addr_maps = [
["bcrt1qmhpq9hxgdglwja6uruc92yne8ekxljgykrfta5", "0xfD0766e7aBe123A25c73c95f6dc3eDe26D0b7263"],
["bcrt1qtqggfdte5jp8duffzmt54aqtqwlv3l8xsjdrhf", "0x4d07A76Db2a281a348d5A5a1833F4322D77799d5"],
["bcrt1qdw7fqrq9n2d530uh05vdm2yvpag2ydm0z67yc5", "0x816a4DDbC26B80602767B13Fb17B2e1785125BE7"],
]
for [wif, rawkey] in priv_keys:
# Adding this line will make the second rawkey import fail
# due to a bug in importprivkey.
#
# Context: Since we have a different ID for each import (eth and non eth),
# Have ID check fails resulting in https://github.com/defich/ain/blob/tests_vmmap/src/wallet/wallet.cpp/#L1872-L1875
# failing when actually trying to insert the key
# However, https://github.com/defich/ain/blob/tests_vmmap/src/wallet/wallet.cpp#L1862
# still sets the keyid in the map, so further imports use that and succeed
#
# self.nodes[0].importprivkey(wif)
self.nodes[0].importprivkey(rawkey)
for [dfi_addr, eth_addr] in addr_maps:
assert_equal(self.nodes[0].addressmap(dfi_addr, AddressConversionType.DVMToEVMAddress), eth_addr)
assert_equal(self.nodes[0].addressmap(eth_addr, AddressConversionType.EVMToDVMAddress), dfi_addr)

def addressmap_valid_address_not_present_should_fail(self):
self.rollback_to(self.start_block_height)
# Give an address that is not own by the node. THis should fail since we don't have the public key of the address.
eth_address = self.nodes[1].getnewaddress("", "eth")
assert_raises_rpc_error(-5, "no full public key for address " + eth_address, self.nodes[0].addressmap, eth_address, AddressConversionType.EVMToDVMAddress)

def addressmap_valid_address_invalid_type_should_fail(self):
self.rollback_to(self.start_block_height)
address = self.nodes[0].getnewaddress("", "legacy")
p2sh_address = self.nodes[0].getnewaddress("", "p2sh-segwit")
eth_address = self.nodes[0].getnewaddress("", "eth")
assert_invalid = lambda *args: assert_raises_rpc_error(-8, "Invalid type parameter", self.nodes[0].addressmap, *args)
assert_invalid(address, 9)
assert_invalid(address, -1)
assert_invalid(eth_address, AddressConversionType.DVMToEVMAddress)
assert_invalid(address, AddressConversionType.EVMToDVMAddress)
assert_invalid(p2sh_address, AddressConversionType.DVMToEVMAddress)
assert_invalid(p2sh_address, AddressConversionType.DVMToEVMAddress)

def addressmap_invalid_address_should_fail(self):
self.rollback_to(self.start_block_height)
# Check that addressmap is failing on wrong input
eth_address = '0x0000000000000000000000000000000000000000'
assert_raises_rpc_error(-5, eth_address + " does not refer to a key", self.nodes[0].addressmap, eth_address, AddressConversionType.EVMToDVMAddress)
assert_raises_rpc_error(-8, "Invalid type parameter", self.nodes[0].addressmap, eth_address, AddressConversionType.DVMToEVMAddress)
assert_raises_rpc_error(-8, "Invalid type parameter", self.nodes[0].addressmap, 'test', AddressConversionType.DVMToEVMAddress)
assert_raises_rpc_error(-8, "Invalid type parameter", self.nodes[0].addressmap, 'test', AddressConversionType.EVMToDVMAddress)

def run_test(self):
self.setup()
# Address map tests
self.addressmap_address_basics_manual_import()
self.addressmap_valid_address_not_present_should_fail()
self.addressmap_valid_address_invalid_type_should_fail()
self.addressmap_invalid_address_should_fail()

if __name__ == '__main__':
addressmapTests().main()
Empty file modified test/functional/feature_commission_fix.py
100644 → 100755
Empty file.
Empty file modified test/functional/feature_evm_contracts.py
100644 → 100755
Empty file.
28 changes: 13 additions & 15 deletions test/functional/feature_evm_vmmap_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,12 @@

class VMMapType:
Auto = 0
AddressDVMToEVM = 1
AddressEVMToDVM = 2
TxHashDVMToEVM = 3
TxHashEVMToEVM = 4
BlockHashDVMToEVM = 5
BlockHashEVMToDVM = 6
BlockNumberDVMToEVM = 7
BlockNumberEVMToDVM = 8
TxHashDVMToEVM = 1
TxHashEVMToEVM = 2
BlockHashDVMToEVM = 3
BlockHashEVMToDVM = 4
BlockNumberDVMToEVM = 5
BlockNumberEVMToDVM = 6

class VMMapTests(DefiTestFramework):
def set_test_params(self):
Expand Down Expand Up @@ -155,8 +153,8 @@ def vmmap_invalid_should_fail(self):
latest_eth_block = self.nodes[0].eth_getBlockByNumber("latest", False)['hash']
fake_evm_tx = '0x0000000000000000000000000000000000000000000000000000000000000000'
assert_err = lambda *args: assert_raises_rpc_error(-32600, None, self.nodes[0].vmmap, *args)
for map_type in range(6):
if map_type in [0, 1, 2]:
for map_type in range(4):
if map_type == 0:
continue # addr types and auto are ignored for this test
assert_raises_rpc_error(-32600, "Key not found: " + fake_evm_tx[2:], self.nodes[0].vmmap, fake_evm_tx, map_type)
assert_err("0x00", map_type)
Expand Down Expand Up @@ -248,7 +246,7 @@ def logvmmaps_block_exist(self):
list_blocks = self.nodes[0].logvmmaps(0)
eth_block = self.nodes[0].eth_getBlockByNumber("latest", False)['hash']
assert_equal(eth_block[2:] in list(list_blocks['indexes'].values()), True)
dfi_block = self.nodes[0].vmmap(eth_block, 6)
dfi_block = self.nodes[0].vmmap(eth_block, VMMapType.BlockHashEVMToDVM)
assert_equal(dfi_block in list(list_blocks['indexes'].keys()), True)

def logvmmaps_invalid_block_should_fail(self):
Expand All @@ -262,10 +260,10 @@ def run_test(self):
self.setup()
# vmmap tests
# self.vmmap_address_basics()
self.vmmap_address_basics_manual_import()
self.vmmap_valid_address_not_present_should_fail()
self.vmmap_valid_address_invalid_type_should_fail()
self.vmmap_invalid_address_should_fail()
# self.vmmap_address_basics_manual_import()
# self.vmmap_valid_address_not_present_should_fail()
# self.vmmap_valid_address_invalid_type_should_fail()
# self.vmmap_invalid_address_should_fail()
self.vmmap_valid_tx_should_succeed()
self.vmmap_valid_block_should_succeed()
self.vmmap_invalid_should_fail()
Expand Down
Empty file modified test/functional/feature_listaccounthistory_multiaccountquery.py
100644 → 100755
Empty file.
Empty file modified test/functional/feature_on_chain_government_voting_scenarios.py
100644 → 100755
Empty file.
1 change: 1 addition & 0 deletions test/functional/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@
'feature_loan_low_interest.py',
'feature_loan_estimatecollateral.py',
'feature_vault_pct_check_factor.py',
'feature_address_map.py',
'p2p_node_network_limited.py',
'p2p_permissions.py',
'feature_blocksdir.py',
Expand Down

0 comments on commit 9a6e2fb

Please sign in to comment.