From 2f46a0d88c9906f1fc1d317a5f7de13357d13721 Mon Sep 17 00:00:00 2001 From: Bushstar Date: Mon, 23 Oct 2023 10:50:29 +0100 Subject: [PATCH 1/3] Get correct compression for encrypted wallet --- src/dfi/rpc_accounts.cpp | 2 ++ src/dfi/rpc_evm.cpp | 2 ++ src/wallet/rpcwallet.cpp | 7 +---- src/wallet/wallet.cpp | 8 +++-- test/functional/feature_evm.py | 53 ++++++++++++++++++++++++++++++++++ 5 files changed, 64 insertions(+), 8 deletions(-) diff --git a/src/dfi/rpc_accounts.cpp b/src/dfi/rpc_accounts.cpp index 2bbc45ab9d..ad9753a051 100644 --- a/src/dfi/rpc_accounts.cpp +++ b/src/dfi/rpc_accounts.cpp @@ -2196,6 +2196,8 @@ UniValue transferdomain(const JSONRPCRequest &request) { pwallet->BlockUntilSyncedToCurrentChain(); + EnsureWalletIsUnlocked(pwallet); + RPCTypeCheck(request.params, {UniValue::VARR}, false); UniValue srcDstArray(UniValue::VARR); diff --git a/src/dfi/rpc_evm.cpp b/src/dfi/rpc_evm.cpp index ada52464ef..395d042232 100644 --- a/src/dfi/rpc_evm.cpp +++ b/src/dfi/rpc_evm.cpp @@ -68,6 +68,8 @@ UniValue evmtx(const JSONRPCRequest &request) { } pwallet->BlockUntilSyncedToCurrentChain(); + EnsureWalletIsUnlocked(pwallet); + const auto fromDest = DecodeDestination(request.params[0].get_str()); if (fromDest.index() != WitV16KeyEthHashType) { throw JSONRPCError(RPC_INVALID_PARAMETER, "from address not an Ethereum address"); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 8063b4b749..2895b1ddde 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4322,12 +4322,7 @@ UniValue addressmap(const JSONRPCRequest &request) { if (key.IsCompressed()) { key.Decompress(); } - const auto erc55 = EncodeDestination(WitnessV16EthHash(key)); - // Check if it's in the wallet. - // Note: Can be removed if the full wallet is migrated. - // Ref: https://github.com/DeFiCh/ain/issues/2604 - AddrToPubKey(pwallet, erc55); - format.pushKV("erc55", erc55); + format.pushKV("erc55", EncodeDestination(WitnessV16EthHash(key))); break; } case AddressConversionType::EVMToDVMAddress: { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index dc342d4754..19aae1d9a9 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4979,10 +4979,14 @@ bool CWallet::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const return true; } - CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address); - if (mi != mapCryptedKeys.end()) + if (const auto mi = mapCryptedKeys.find(address); mi != mapCryptedKeys.end()) { vchPubKeyOut = (*mi).second.first; + if (!vchPubKeyOut.IsCompressed() && address.type == KeyAddressType::COMPRESSED) { + vchPubKeyOut.Compress(); + } else if (vchPubKeyOut.IsCompressed() && address.type == KeyAddressType::UNCOMPRESSED) { + vchPubKeyOut.Decompress(); + } return true; } // Check for watch-only pubkeys diff --git a/test/functional/feature_evm.py b/test/functional/feature_evm.py index 5483a5e5b9..a153dd49db 100755 --- a/test/functional/feature_evm.py +++ b/test/functional/feature_evm.py @@ -94,6 +94,9 @@ def run_test(self): # Toggle EVM self.toggle_evm_enablement() + # Test Eth on encrypted wallet + self.encrypt_wallet() + def test_tx_without_chainid(self): node = self.nodes[0] @@ -1340,6 +1343,56 @@ def toggle_evm_enablement(self): int(evm_enabling_block["number"], base=16) + 1, ) + def encrypt_wallet(self): + # Test address + address = "0xa43D1AdBe968BFE45ECfbFa623a25077fd4F5db8" + priv_key = "1ba6d9404e882346a236a6742722fe79d822e2182d6808ab66cc30b7dd07c5b7" + pub_key = "0426f07fbd27600beccd6d4a1a3bbcfd2cced7212e201c2ff2970214ed19ba92f473e102d978c65626b46e61a4b4f770e51b944f10462a111e170aad5b65e638bd" + + # Encrypt wallet + self.nodes[0].encryptwallet("test") + self.stop_nodes() + self.start_nodes() + + # Unencrypt wallet + self.nodes[0].walletpassphrase("test", 600) + + # Import address + self.nodes[0].importprivkey(priv_key) + + # Check pubkey + assert_equal(pub_key, self.nodes[0].getaddressinfo(address)["pubkey"]) + + # Fund EVM address + self.nodes[0].transferdomain( + [ + { + "src": {"address": self.address, "amount": "0.1@DFI", "domain": 2}, + "dst": { + "address": address, + "amount": "0.1@DFI", + "domain": 3, + }, + } + ] + ) + self.nodes[0].generate(1) + + # Transfer funds back + self.nodes[0].transferdomain( + [ + { + "src": {"address": address, "amount": "0.1@DFI", "domain": 3}, + "dst": { + "address": self.address, + "amount": "0.1@DFI", + "domain": 2, + }, + } + ] + ) + self.nodes[0].generate(1) + if __name__ == "__main__": EVMTest().main() From a62aa93c8c0767e799c1ebcf077770e0d4878ea8 Mon Sep 17 00:00:00 2001 From: Bushstar Date: Mon, 23 Oct 2023 11:19:10 +0100 Subject: [PATCH 2/3] Add test for addressmap --- test/functional/feature_evm.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/functional/feature_evm.py b/test/functional/feature_evm.py index a153dd49db..e21760789e 100755 --- a/test/functional/feature_evm.py +++ b/test/functional/feature_evm.py @@ -1363,6 +1363,12 @@ def encrypt_wallet(self): # Check pubkey assert_equal(pub_key, self.nodes[0].getaddressinfo(address)["pubkey"]) + # Check equivalent DVM address + assert_equal( + "bcrt1qkhd438yhrvnleflep3xlxj4xvnm4q7r0wsxzya", + self.nodes[0].addressmap(address, 2)["format"]["bech32"], + ) + # Fund EVM address self.nodes[0].transferdomain( [ From 4e05495e9d7a4b2c500e164ad441e477a2cfc846 Mon Sep 17 00:00:00 2001 From: Bushstar Date: Tue, 24 Oct 2023 05:43:43 +0100 Subject: [PATCH 3/3] Add helper function. Convert pubkey for watch address. --- src/script/signingprovider.cpp | 9 ++------- src/script/signingprovider.h | 8 ++++++++ src/wallet/wallet.cpp | 10 +++------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/script/signingprovider.cpp b/src/script/signingprovider.cpp index 491c27ac72..61b064d4b7 100644 --- a/src/script/signingprovider.cpp +++ b/src/script/signingprovider.cpp @@ -98,13 +98,8 @@ bool FillableSigningProvider::GetPubKey(const CKeyID &address, CPubKey &vchPubKe if (!GetKey(address, key)) { return false; } - auto pubkey = key.GetPubKey(); - if (!pubkey.IsCompressed() && address.type == KeyAddressType::COMPRESSED) { - pubkey.Compress(); - } else if (pubkey.IsCompressed() && address.type == KeyAddressType::UNCOMPRESSED) { - pubkey.Decompress(); - } - vchPubKeyOut = pubkey; + vchPubKeyOut = key.GetPubKey(); + ResolveKeyCompression(address.type, vchPubKeyOut); return true; } diff --git a/src/script/signingprovider.h b/src/script/signingprovider.h index 927fdceead..9064bedf3a 100644 --- a/src/script/signingprovider.h +++ b/src/script/signingprovider.h @@ -89,4 +89,12 @@ class FillableSigningProvider : public SigningProvider /** Return the CKeyID of the key involved in a script (if there is a unique one). */ CKeyID GetKeyOrDefaultFromDestination(const SigningProvider& store, const CTxDestination& dest); +inline void ResolveKeyCompression(const KeyAddressType type, CPubKey &pubkey) { + if (!pubkey.IsCompressed() && type == KeyAddressType::COMPRESSED) { + pubkey.Compress(); + } else if (pubkey.IsCompressed() && type == KeyAddressType::UNCOMPRESSED) { + pubkey.Decompress(); + } +} + #endif // DEFI_SCRIPT_SIGNINGPROVIDER_H diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 19aae1d9a9..378fe23c23 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4961,9 +4961,9 @@ bool CWallet::GetKey(const CKeyID &address, CKey& keyOut) const bool CWallet::GetWatchPubKey(const CKeyID &address, CPubKey &pubkey_out) const { LOCK(cs_KeyStore); - WatchKeyMap::const_iterator it = mapWatchKeys.find(address); - if (it != mapWatchKeys.end()) { + if (const auto it = mapWatchKeys.find(address); it != mapWatchKeys.end()) { pubkey_out = it->second; + ResolveKeyCompression(address.type, pubkey_out); return true; } return false; @@ -4982,11 +4982,7 @@ bool CWallet::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const if (const auto mi = mapCryptedKeys.find(address); mi != mapCryptedKeys.end()) { vchPubKeyOut = (*mi).second.first; - if (!vchPubKeyOut.IsCompressed() && address.type == KeyAddressType::COMPRESSED) { - vchPubKeyOut.Compress(); - } else if (vchPubKeyOut.IsCompressed() && address.type == KeyAddressType::UNCOMPRESSED) { - vchPubKeyOut.Decompress(); - } + ResolveKeyCompression(address.type, vchPubKeyOut); return true; } // Check for watch-only pubkeys