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

Populate EVM Address in CryptoTranscation #5010

Merged
merged 15 commits into from Mar 16, 2023
Expand Up @@ -17,6 +17,7 @@
package com.hedera.node.app.service.mono.txns.crypto;

import static com.hedera.node.app.service.mono.context.BasicTransactionContext.EMPTY_KEY;
import static com.hedera.node.app.service.mono.ledger.accounts.AliasManager.tryAddressRecovery;
import static com.hedera.node.app.service.mono.records.TxnAwareRecordsHistorian.DEFAULT_SOURCE_ID;
import static com.hedera.node.app.service.mono.utils.MiscUtils.asFcKeyUnchecked;
import static com.hedera.node.app.service.mono.utils.MiscUtils.asPrimitiveKeyUnchecked;
Expand All @@ -25,6 +26,7 @@
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.OK;

import com.google.protobuf.ByteString;
import com.hedera.node.app.service.evm.utils.EthSigsUtils;
import com.hedera.node.app.service.mono.context.SideEffectsTracker;
import com.hedera.node.app.service.mono.context.TransactionContext;
import com.hedera.node.app.service.mono.context.primitives.StateView;
Expand Down Expand Up @@ -142,9 +144,9 @@ protected abstract void trackSigImpactIfNeeded(
* after those changes are applied atomically, the returned fee must be given to the funding
* account!
*
* @param change a triggering change with unique alias
* @param change a triggering change with unique alias
* @param accountsLedger the accounts ledger to use for the provisional creation
* @param changes list of all changes need to construct tokenAliasMap
* @param changes list of all changes need to construct tokenAliasMap
* @return the fee charged for the auto-creation if ok, a failure reason otherwise
*/
public Pair<ResponseCodeEnum, Long> create(
Expand Down Expand Up @@ -211,6 +213,17 @@ public Pair<ResponseCodeEnum, Long> create(
sideEffects.trackAutoCreation(newId);

final var childRecord = creator.createSuccessfulSyntheticRecord(NO_CUSTOM_FEES, sideEffects, memo);

if (!isAliasEVMAddress) {
final var key = asPrimitiveKeyUnchecked(alias);

if (key.hasECDSASecp256K1()) {
final JKey jKey = asFcKeyUnchecked(key);
final var evmAddress = tryAddressRecovery(jKey, EthSigsUtils::recoverAddressFromPubKey);
randered marked this conversation as resolved.
Show resolved Hide resolved
childRecord.setEvmAddress(evmAddress);
}
}

childRecord.setFee(fee);

final var inProgress =
Expand Down
Expand Up @@ -26,6 +26,7 @@
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.MAX_ENTITIES_IN_PRICE_REGIME_HAVE_BEEN_CREATED;
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.NOT_SUPPORTED;
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.OK;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
Expand Down Expand Up @@ -208,6 +209,10 @@ void happyPathEDKeyAliasWithHbarChangeWorks() {
assertEquals(totalFee, mockBuilder.getFee());
assertEquals(Pair.of(OK, totalFee), result);
assertTrue(subject.getTokenAliasMap().isEmpty());

final var pendingCreations = subject.pendingCreations.get(0);
final var record = pendingCreations.recordBuilder().build();
assertArrayEquals(new byte[0], record.getEvmAddress());
}

@Test
Expand Down Expand Up @@ -237,6 +242,11 @@ void happyPathECKeyAliasWithHbarChangeWorks() throws InvalidProtocolBufferExcept
verify(accountsLedger, never())
.set(createdNum.toGrpcAccountId(), AccountProperty.MAX_AUTOMATIC_ASSOCIATIONS, 1);
verify(recordsHistorian).trackPrecedingChildRecord(DEFAULT_SOURCE_ID, syntheticECAliasCreation, mockBuilder);

final var pendingCreations = subject.pendingCreations.get(0);
final var record = pendingCreations.recordBuilder().build();
assertArrayEquals(evmAddress.toByteArray(), record.getEvmAddress());

assertEquals(totalFee, mockBuilder.getFee());
assertEquals(Pair.of(OK, totalFee), result);
assertTrue(subject.getTokenAliasMap().isEmpty());
Expand Down
Expand Up @@ -205,7 +205,8 @@ public List<HapiSpec> getSpecsInSuite() {
transferHbarsToEVMAddressAlias(),
transferFungibleToEVMAddressAlias(),
transferNonFungibleToEVMAddressAlias(),
hollowAccountCompletionWithTokenTransfer());
hollowAccountCompletionWithTokenTransfer(),
transferHbarsToECDSAKey());
}

private HapiSpec canAutoCreateWithHbarAndTokenTransfers() {
Expand Down Expand Up @@ -1593,6 +1594,52 @@ private HapiSpec transferHbarsToEVMAddressAlias() {
.has(accountWith().expectedBalanceWithChargedUsd(3 * ONE_HBAR, 0, 0)));
}

private HapiSpec transferHbarsToECDSAKey() {

final AtomicReference<ByteString> evmAddress = new AtomicReference<>();
final var transferToECDSA = "transferToЕCDSA";

return defaultHapiSpec("transferHbarsToECDSAKey")
.given(
newKeyNamed(SECP_256K1_SOURCE_KEY).shape(SECP_256K1_SHAPE),
cryptoCreate(PAYER).balance(10 * ONE_HBAR),
withOpContext((spec, opLog) -> {
final var registry = spec.registry();
final var ecdsaKey = registry.getKey(SECP_256K1_SOURCE_KEY);
final var tmp = ecdsaKey.getECDSASecp256K1().toByteArray();
final var addressBytes = recoverAddressFromPubKey(tmp);
final var evmAddressBytes = ByteString.copyFrom(addressBytes);
evmAddress.set(evmAddressBytes);
}))
.when(withOpContext((spec, opLog) -> {
final var hbarCreateTransfer = cryptoTransfer(
tinyBarsFromAccountToAlias(PAYER, SECP_256K1_SOURCE_KEY, ONE_HBAR))
.via(transferToECDSA);

final var op1 = cryptoTransfer(tinyBarsFromTo(PAYER, evmAddress.get(), ONE_HBAR));

final var op2 = getAliasedAccountInfo(SECP_256K1_SOURCE_KEY)
.has(accountWith()
.balance(2 * ONE_HBAR)
.alias(SECP_256K1_SOURCE_KEY)
.key(SECP_256K1_SOURCE_KEY)
.autoRenew(THREE_MONTHS_IN_SECONDS)
.receiverSigReq(false)
.memo(AUTO_MEMO));

final var op3 = childRecordsCheck(
transferToECDSA,
SUCCESS,
recordWith()
.evmAddress(evmAddress.get())
.hasNoAlias()
.status(SUCCESS));

allRunFor(spec, hbarCreateTransfer, op1, op2, op3);
}))
.then(getTxnRecord(transferToECDSA).andAllChildRecords().logged());
}

private HapiSpec transferFungibleToEVMAddressAlias() {

final var fungibleToken = "fungibleToken";
Expand Down