Skip to content

Commit

Permalink
Merge branch '05396-write-to-preconsensus-stream-2' into 05786-5396-m…
Browse files Browse the repository at this point in the history
…isc-startup-improvements

Signed-off-by: Cody Littley <cody@swirldslabs.com>
  • Loading branch information
Cody Littley committed Mar 28, 2023
2 parents d3eace3 + 4a1283c commit 84d4b64
Show file tree
Hide file tree
Showing 27 changed files with 907 additions and 219 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ hedera.workflows.enabled=
accounts.maxNumber=5_000_000
autoCreation.enabled=true
lazyCreation.enabled=true
cryptoCreateWithAlias.enabled=false
cryptoCreateWithAlias.enabled=true
entities.limitTokenAssociations=false
balances.exportDir.path=/opt/hgcapp/accountBalances/
balances.exportEnabled=true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.hedera.node.app.service.mono.sigs.order;

import static com.hedera.node.app.hapi.utils.CommonUtils.functionOf;
import static com.hedera.node.app.service.evm.utils.EthSigsUtils.recoverAddressFromPubKey;
import static com.hedera.node.app.service.mono.sigs.order.KeyOrderingFailure.IMMUTABLE_ACCOUNT;
import static com.hedera.node.app.service.mono.sigs.order.KeyOrderingFailure.IMMUTABLE_CONTRACT;
import static com.hedera.node.app.service.mono.sigs.order.KeyOrderingFailure.INVALID_ACCOUNT;
Expand All @@ -32,6 +33,7 @@

import com.hedera.node.app.hapi.utils.exception.UnknownHederaFunctionality;
import com.hedera.node.app.service.mono.legacy.core.jproto.JKey;
import com.hedera.node.app.service.mono.legacy.core.jproto.JWildcardECDSAKey;
import com.hedera.node.app.service.mono.sigs.metadata.SigMetadataLookup;
import com.hedera.node.app.service.mono.sigs.metadata.TokenSigningMetadata;
import com.hedera.node.app.service.mono.state.submerkle.EntityId;
Expand Down Expand Up @@ -69,6 +71,7 @@
import com.hederahashgraph.api.proto.java.TransactionBody;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
Expand Down Expand Up @@ -733,14 +736,24 @@ private List<JKey> mutable(final List<JKey> required) {

private <T> SigningOrderResult<T> cryptoCreate(
final CryptoCreateTransactionBody op, final SigningOrderResultFactory<T> factory) {
if (!op.getReceiverSigRequired()) {
return SigningOrderResult.noKnownKeys();
} else {
final var candidate = asUsableFcKey(op.getKey());
return candidate.isPresent()
? factory.forValidOrder(List.of(candidate.get()))
: SigningOrderResult.noKnownKeys();
final var required = new ArrayList<JKey>();
final var key = op.getKey();
final var alias = op.getAlias();
if (!alias.isEmpty()) {
// semantic checks should have already verified alias is a valid evm address
// add evm address key to req keys only if it is derived from a key, diff than the admin key
final var isAliasDerivedFromDiffKey = !key.hasECDSASecp256K1()
|| !Arrays.equals(
recoverAddressFromPubKey(key.getECDSASecp256K1().toByteArray()), alias.toByteArray());
if (isAliasDerivedFromDiffKey) {
required.add(new JWildcardECDSAKey(alias.toByteArray(), false));
}
}
if (op.getReceiverSigRequired()) {
final var candidate = asUsableFcKey(key);
candidate.ifPresent(required::add);
}
return factory.forValidOrder(required);
}

private <T> SigningOrderResult<T> topicCreate(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
import com.hederahashgraph.api.proto.java.TokenWipeAccountTransactionBody;
import com.hederahashgraph.api.proto.java.TransactionBody;
import com.hederahashgraph.api.proto.java.TransactionID;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.math.BigInteger;
import java.util.ArrayList;
Expand Down Expand Up @@ -296,8 +297,9 @@ public TransactionBody.Builder createMint(final MintWrapper mintWrapper) {
return TransactionBody.newBuilder().setTokenMint(builder);
}

public TransactionBody.Builder createFungibleApproval(final ApproveWrapper approveWrapper) {
return createNonfungibleApproval(approveWrapper, null, null);
public TransactionBody.Builder createFungibleApproval(
@NonNull final ApproveWrapper approveWrapper, @NonNull EntityId ownerId) {
return createNonfungibleApproval(approveWrapper, ownerId, null);
}

public TransactionBody.Builder createNonfungibleApproval(
Expand All @@ -308,6 +310,7 @@ public TransactionBody.Builder createNonfungibleApproval(
if (approveWrapper.isFungible()) {
builder.addTokenAllowances(TokenAllowance.newBuilder()
.setTokenId(approveWrapper.tokenId())
.setOwner(Objects.requireNonNull(ownerId).toGrpcAccountId())
.setSpender(approveWrapper.spender())
.setAmount(approveWrapper.amount().longValueExact())
.build());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ public TransactionBody.Builder body(final Bytes input, final UnaryOperator<byte[
approveOp = decodeTokenApprove(nestedInput, tokenId, isFungible, aliasResolver, ledgers);

if (approveOp.isFungible()) {
transactionBody = syntheticTxnFactory.createFungibleApproval(approveOp);
transactionBody = syntheticTxnFactory.createFungibleApproval(approveOp, operatorId);
} else {
final var nftId =
NftId.fromGrpc(approveOp.tokenId(), approveOp.serialNumber().longValueExact());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@

package com.hedera.node.app.service.mono.txns.crypto.validators;

import static com.hedera.node.app.service.evm.utils.EthSigsUtils.recoverAddressFromPubKey;
import static com.hedera.node.app.service.mono.ledger.accounts.HederaAccountCustomizer.hasStakedId;
import static com.hedera.node.app.service.mono.utils.EntityIdUtils.EVM_ADDRESS_SIZE;
import static com.hedera.node.app.service.mono.utils.EntityNum.MISSING_NUM;
import static com.hedera.node.app.service.mono.utils.MiscUtils.asFcKeyUnchecked;
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.ALIAS_ALREADY_ASSIGNED;
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.AUTORENEW_DURATION_NOT_IN_RANGE;
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.BAD_ENCODING;
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.INVALID_ADMIN_KEY;
Expand All @@ -37,7 +37,6 @@
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.REQUESTED_NUM_AUTOMATIC_ASSOCIATIONS_EXCEEDS_ASSOCIATION_LIMIT;
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.STAKING_NOT_ENABLED;

import com.google.protobuf.ByteString;
import com.hedera.node.app.service.evm.accounts.HederaEvmContractAliases;
import com.hedera.node.app.service.mono.context.NodeInfo;
import com.hedera.node.app.service.mono.context.properties.GlobalDynamicProperties;
Expand All @@ -47,7 +46,6 @@
import com.hederahashgraph.api.proto.java.AccountID;
import com.hederahashgraph.api.proto.java.CryptoCreateTransactionBody;
import com.hederahashgraph.api.proto.java.ResponseCodeEnum;
import java.util.Arrays;
import java.util.function.Supplier;
import javax.inject.Inject;
import javax.inject.Singleton;
Expand Down Expand Up @@ -77,17 +75,14 @@ public CryptoCreateChecks(

@SuppressWarnings("java:S1874")
public ResponseCodeEnum cryptoCreateValidation(final CryptoCreateTransactionBody op) {

var memoValidity = validator.memoCheck(op.getMemo());
final var memoValidity = validator.memoCheck(op.getMemo());
if (memoValidity != OK) {
return memoValidity;
}

var kayAliasAndEvmAddressCombinationsValidity = validateKeyAliasAndEvmAddressCombinations(op);
if (kayAliasAndEvmAddressCombinationsValidity != OK) {
return kayAliasAndEvmAddressCombinationsValidity;
final var keyAliasAndEvmAddressCombinationsValidity = validateKeyAliasAndEvmAddressCombinations(op);
if (keyAliasAndEvmAddressCombinationsValidity != OK) {
return keyAliasAndEvmAddressCombinationsValidity;
}

if (op.getInitialBalance() < 0L) {
return INVALID_INITIAL_BALANCE;
}
Expand Down Expand Up @@ -136,34 +131,16 @@ private ResponseCodeEnum validateKey(final CryptoCreateTransactionBody op) {
return OK;
}

private ResponseCodeEnum validateEcdsaKey(final ByteString ecdsaKey, final byte[] evmAddress) {
if (ecdsaKey.isEmpty()) {
return INVALID_ADMIN_KEY;
}
final var recoveredEvmAddress = recoverAddressFromPubKey(ecdsaKey.toByteArray());
if (!Arrays.equals(recoveredEvmAddress, evmAddress)) {
return INVALID_ALIAS_KEY;
}
return OK;
}

private boolean tooManyAutoAssociations(final int n) {
return n > MAX_CHARGEABLE_AUTO_ASSOCIATIONS
|| (dynamicProperties.areTokenAssociationsLimited() && n > dynamicProperties.maxTokensPerAccount());
}

private ResponseCodeEnum isUsedAsAliasCheck(final ByteString alias) {
if (!aliasManager.lookupIdBy(alias).equals(MISSING_NUM)) {
return INVALID_ALIAS_KEY;
}
return OK;
}

private ResponseCodeEnum validateKeyAliasAndEvmAddressCombinations(final CryptoCreateTransactionBody op) {
if (onlyKeyProvided(op)) {
return validateKey(op);
} else if (onlyAliasProvided(op)) {
return INVALID_ALIAS_KEY;
return dynamicProperties.isCryptoCreateWithAliasEnabled() ? INVALID_ALIAS_KEY : NOT_SUPPORTED;
} else if (keyAndAliasProvided(op)) {
return validateKeyAndAliasProvidedCase(op);
} else {
Expand All @@ -185,28 +162,22 @@ public static boolean onlyAliasProvided(CryptoCreateTransactionBody op) {
}

private ResponseCodeEnum validateKeyAndAliasProvidedCase(final CryptoCreateTransactionBody op) {
if (!dynamicProperties.isCryptoCreateWithAliasEnabled()) {
return NOT_SUPPORTED;
}
final var keyValidity = validateKey(op);
if (keyValidity != OK) {
return keyValidity;
}

if (op.getAlias().size() != EVM_ADDRESS_SIZE) {
return INVALID_ALIAS_KEY;
}

if (!dynamicProperties.isCryptoCreateWithAliasEnabled()) {
return NOT_SUPPORTED;
}

if (HederaEvmContractAliases.isMirror(op.getAlias().toByteArray())) {
return INVALID_ALIAS_KEY;
}

var isEvmAddressUsedCheck = isUsedAsAliasCheck(op.getAlias());
if (isEvmAddressUsedCheck != OK) {
return isEvmAddressUsedCheck;
if (!aliasManager.lookupIdBy(op.getAlias()).equals(MISSING_NUM)) {
return ALIAS_ALREADY_ASSIGNED;
}

return validateEcdsaKey(op.getKey().getECDSASecp256K1(), op.getAlias().toByteArray());
return OK;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ hedera.workflows.enabled=
accounts.maxNumber=5_000_000
autoCreation.enabled=true
lazyCreation.enabled=true
cryptoCreateWithAlias.enabled=false
cryptoCreateWithAlias.enabled=true
entities.limitTokenAssociations=false
balances.exportDir.path=/opt/hgcapp/accountBalances/
balances.exportEnabled=true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ class BootstrapPropertiesTest {
entry(LEDGER_TOTAL_TINY_BAR_FLOAT, 5000000000000000000L),
entry(AUTO_CREATION_ENABLED, true),
entry(LAZY_CREATION_ENABLED, true),
entry(CRYPTO_CREATE_WITH_ALIAS_ENABLED, false),
entry(CRYPTO_CREATE_WITH_ALIAS_ENABLED, true),
entry(AUTO_RENEW_TARGET_TYPES, Collections.emptySet()),
entry(AUTO_RENEW_NUM_OF_ENTITIES_TO_SCAN, 100),
entry(AUTO_RENEW_MAX_NUM_OF_ENTITIES_TO_RENEW_OR_DELETE, 2),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.hedera.node.app.service.mono.sigs.order;

import static com.hedera.node.app.service.evm.utils.EthSigsUtils.recoverAddressFromPubKey;
import static com.hedera.node.app.service.mono.sigs.metadata.DelegatingSigMetadataLookup.PRETEND_SIGNING_TIME;
import static com.hedera.node.app.service.mono.sigs.metadata.DelegatingSigMetadataLookup.defaultLookupsFor;
import static com.hedera.node.app.service.mono.sigs.order.CodeOrderResultFactory.CODE_ORDER_RESULT_FACTORY;
Expand Down Expand Up @@ -91,7 +92,13 @@
import static com.hedera.test.factories.scenarios.CryptoAllowanceScenarios.CRYPTO_DELETE_ALLOWANCE_SCENARIO;
import static com.hedera.test.factories.scenarios.CryptoAllowanceScenarios.CRYPTO_DELETE_ALLOWANCE_SELF_SCENARIO;
import static com.hedera.test.factories.scenarios.CryptoAllowanceScenarios.CRYPTO_DELETE_NFT_ALLOWANCE_MISSING_OWNER_SCENARIO;
import static com.hedera.test.factories.scenarios.CryptoCreateScenarios.CRYPTO_CREATE_NO_RECEIVER_SIG_ECDSA_ADMIN_KEY_DIFFERENT_EVM_ADDRESS_ALIAS_SCENARIO;
import static com.hedera.test.factories.scenarios.CryptoCreateScenarios.CRYPTO_CREATE_NO_RECEIVER_SIG_ECDSA_ADMIN_KEY_EVM_ADDRESS_ALIAS_FROM_SAME_KEY_SCENARIO;
import static com.hedera.test.factories.scenarios.CryptoCreateScenarios.CRYPTO_CREATE_NO_RECEIVER_SIG_ED_ADMIN_KEY_EVM_ADDRESS_ALIAS_SCENARIO;
import static com.hedera.test.factories.scenarios.CryptoCreateScenarios.CRYPTO_CREATE_NO_RECEIVER_SIG_SCENARIO;
import static com.hedera.test.factories.scenarios.CryptoCreateScenarios.CRYPTO_CREATE_RECEIVER_SIG_ECDSA_ADMIN_KEY_DIFFERENT_EVM_ADDRESS_ALIAS_SCENARIO;
import static com.hedera.test.factories.scenarios.CryptoCreateScenarios.CRYPTO_CREATE_RECEIVER_SIG_ECDSA_ADMIN_KEY_EVM_ADDRESS_ALIAS_FROM_SAME_KEY_SCENARIO;
import static com.hedera.test.factories.scenarios.CryptoCreateScenarios.CRYPTO_CREATE_RECEIVER_SIG_ED_ADMIN_KEY_EVM_ADDRESS_ALIAS_SCENARIO;
import static com.hedera.test.factories.scenarios.CryptoCreateScenarios.CRYPTO_CREATE_RECEIVER_SIG_SCENARIO;
import static com.hedera.test.factories.scenarios.CryptoDeleteScenarios.CRYPTO_DELETE_MISSING_RECEIVER_SIG_SCENARIO;
import static com.hedera.test.factories.scenarios.CryptoDeleteScenarios.CRYPTO_DELETE_MISSING_TARGET;
Expand Down Expand Up @@ -280,6 +287,8 @@
import static com.hedera.test.factories.txns.ConsensusCreateTopicFactory.SIMPLE_TOPIC_ADMIN_KEY;
import static com.hedera.test.factories.txns.ContractCreateFactory.DEFAULT_ADMIN_KT;
import static com.hedera.test.factories.txns.CryptoCreateFactory.DEFAULT_ACCOUNT_KT;
import static com.hedera.test.factories.txns.CryptoCreateFactory.ECDSA_KT;
import static com.hedera.test.factories.txns.CryptoCreateFactory.ECDSA_KT_2;
import static com.hedera.test.factories.txns.FileCreateFactory.DEFAULT_WACL_KT;
import static com.hedera.test.factories.txns.SignedTxnFactory.DEFAULT_PAYER_KT;
import static com.hedera.test.factories.txns.SignedTxnFactory.MASTER_PAYER_ID;
Expand All @@ -302,6 +311,7 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.iterableWithSize;
import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
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.assertTrue;
Expand Down Expand Up @@ -530,6 +540,101 @@ void getsCryptoCreateReceiverSigReq() throws Throwable {
assertThat(sanityRestored(summary.getOrderedKeys()), contains(DEFAULT_ACCOUNT_KT.asKey()));
}

@Test
void getsCryptoCreateReceiverSigEDAdminEvmAddressAlias() throws Throwable {
// given:
setupFor(CRYPTO_CREATE_RECEIVER_SIG_ED_ADMIN_KEY_EVM_ADDRESS_ALIAS_SCENARIO);

// when:
final var summary = subject.keysForOtherParties(txn, summaryFactory);

// then:
assertThat(summary.getOrderedKeys(), iterableWithSize(2));
assertArrayEquals(
recoverAddressFromPubKey(ECDSA_KT.asKey().getECDSASecp256K1().toByteArray()),
summary.getOrderedKeys().get(0).getWildcardECDSAKey().getEvmAddress());
assertFalse(summary.getOrderedKeys().get(0).getWildcardECDSAKey().isForHollowAccount());
assertEquals(
DEFAULT_ACCOUNT_KT.asKey(),
sanityRestored(List.of(summary.getOrderedKeys().get(1))).get(0));
}

@Test
void getsCryptoCreateNoReceiverSigEDAdminEvmAddressAlias() throws Throwable {
// given:
setupFor(CRYPTO_CREATE_NO_RECEIVER_SIG_ED_ADMIN_KEY_EVM_ADDRESS_ALIAS_SCENARIO);

// when:
final var summary = subject.keysForOtherParties(txn, summaryFactory);

// then:
assertThat(summary.getOrderedKeys(), iterableWithSize(1));
assertArrayEquals(
recoverAddressFromPubKey(ECDSA_KT.asKey().getECDSASecp256K1().toByteArray()),
summary.getOrderedKeys().get(0).getWildcardECDSAKey().getEvmAddress());
assertFalse(summary.getOrderedKeys().get(0).getWildcardECDSAKey().isForHollowAccount());
}

@Test
void getsCryptoCreateNoReceiverSigECDSAdminEvmAddressAlias() throws Throwable {
// given:
setupFor(CRYPTO_CREATE_NO_RECEIVER_SIG_ECDSA_ADMIN_KEY_DIFFERENT_EVM_ADDRESS_ALIAS_SCENARIO);

// when:
final var summary = subject.keysForOtherParties(txn, summaryFactory);

// then:
assertThat(summary.getOrderedKeys(), iterableWithSize(1));
assertArrayEquals(
recoverAddressFromPubKey(ECDSA_KT_2.asKey().getECDSASecp256K1().toByteArray()),
summary.getOrderedKeys().get(0).getWildcardECDSAKey().getEvmAddress());
assertFalse(summary.getOrderedKeys().get(0).getWildcardECDSAKey().isForHollowAccount());
}

@Test
void getsCryptoCreateReceiverSigECDSAAdminEvmAddressAlias() throws Throwable {
// given:
setupFor(CRYPTO_CREATE_RECEIVER_SIG_ECDSA_ADMIN_KEY_DIFFERENT_EVM_ADDRESS_ALIAS_SCENARIO);

// when:
final var summary = subject.keysForOtherParties(txn, summaryFactory);

// then:
assertThat(summary.getOrderedKeys(), iterableWithSize(2));
assertArrayEquals(
recoverAddressFromPubKey(ECDSA_KT_2.asKey().getECDSASecp256K1().toByteArray()),
summary.getOrderedKeys().get(0).getWildcardECDSAKey().getEvmAddress());
assertFalse(summary.getOrderedKeys().get(0).getWildcardECDSAKey().isForHollowAccount());
assertEquals(
ECDSA_KT.asKey(),
sanityRestored(List.of(summary.getOrderedKeys().get(1))).get(0));
}

@Test
void getsCryptoCreateReceiverSigECDSAAdminEvmAddressAliasFromSameKey() throws Throwable {
// given:
setupFor(CRYPTO_CREATE_RECEIVER_SIG_ECDSA_ADMIN_KEY_EVM_ADDRESS_ALIAS_FROM_SAME_KEY_SCENARIO);

// when:
final var summary = subject.keysForOtherParties(txn, summaryFactory);

// then:
assertThat(summary.getOrderedKeys(), iterableWithSize(1));
assertThat(sanityRestored(summary.getOrderedKeys()), contains(ECDSA_KT.asKey()));
}

@Test
void getsCryptoCreateNoReceiverSigECDSAAdminEvmAddressAliasFromSameKey() throws Throwable {
// given:
setupFor(CRYPTO_CREATE_NO_RECEIVER_SIG_ECDSA_ADMIN_KEY_EVM_ADDRESS_ALIAS_FROM_SAME_KEY_SCENARIO);

// when:
final var summary = subject.keysForOtherParties(txn, summaryFactory);

// then:
assertThat(summary.getOrderedKeys(), iterableWithSize(0));
}

@Test
void getsCryptoCreateReceiverSigReqWithCustomPayer() throws Throwable {
// given:
Expand Down
Loading

0 comments on commit 84d4b64

Please sign in to comment.