Skip to content

Commit

Permalink
feat: Implement pending state for airdrop purposes (#14276)
Browse files Browse the repository at this point in the history
Signed-off-by: ibankov <[email protected]>
Signed-off-by: Valentin Tronkov <[email protected]>
Signed-off-by: Valentin Tronkov <[email protected]>
Co-authored-by: Ivan Bankov <[email protected]>
Co-authored-by: Neeharika Sompalli <[email protected]>
  • Loading branch information
3 people authored Jul 22, 2024
1 parent 9f01a6e commit bbf1254
Show file tree
Hide file tree
Showing 24 changed files with 837 additions and 9 deletions.
3 changes: 2 additions & 1 deletion hapi/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ tasks.cloneHederaProtobufs {
// uncomment below to use a specific tag
// tag = "v0.51.0"
// uncomment below to use a specific branch
branch = "main"
// branch = "main"
branch = "hip-904-proto-updates"
}

sourceSets {
Expand Down
5 changes: 4 additions & 1 deletion hapi/src/main/java/com/hedera/hapi/util/HapiUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -228,12 +228,15 @@ public static HederaFunctionality functionOf(final TransactionBody txn) throws U
case TOKEN_UPDATE -> HederaFunctionality.TOKEN_UPDATE;
case TOKEN_UPDATE_NFTS -> HederaFunctionality.TOKEN_UPDATE_NFTS;
case TOKEN_WIPE -> HederaFunctionality.TOKEN_ACCOUNT_WIPE;
case TOKEN_REJECT -> HederaFunctionality.TOKEN_REJECT;
case UTIL_PRNG -> HederaFunctionality.UTIL_PRNG;
case UNCHECKED_SUBMIT -> HederaFunctionality.UNCHECKED_SUBMIT;
case NODE_CREATE -> HederaFunctionality.NODE_CREATE;
case NODE_UPDATE -> HederaFunctionality.NODE_UPDATE;
case NODE_DELETE -> HederaFunctionality.NODE_DELETE;
case TOKEN_REJECT -> HederaFunctionality.TOKEN_REJECT;
case TOKEN_AIRDROP -> HederaFunctionality.TOKEN_AIRDROP;
case TOKEN_CANCEL_AIRDROP -> HederaFunctionality.TOKEN_CANCEL_AIRDROP;
case TOKEN_CLAIM_AIRDROP -> HederaFunctionality.TOKEN_CLAIM_AIRDROP;
case UNSET -> throw new UnknownHederaFunctionality();
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,12 +320,15 @@ private static <T extends Record, R extends GeneratedMessageV3> R explicitPbjToP
case TokenUnpause -> HederaFunctionality.TOKEN_UNPAUSE;
case TokenUpdate -> HederaFunctionality.TOKEN_UPDATE;
case TokenUpdateNfts -> HederaFunctionality.TOKEN_UPDATE_NFTS;
case TokenReject -> HederaFunctionality.TOKEN_REJECT;
case TransactionGetReceipt -> HederaFunctionality.TRANSACTION_GET_RECEIPT;
case TransactionGetRecord -> HederaFunctionality.TRANSACTION_GET_RECORD;
case TransactionGetFastRecord -> HederaFunctionality.TRANSACTION_GET_FAST_RECORD;
case UncheckedSubmit -> HederaFunctionality.UNCHECKED_SUBMIT;
case UtilPrng -> HederaFunctionality.UTIL_PRNG;
case TokenReject -> HederaFunctionality.TOKEN_REJECT;
case TokenAirdrop -> HederaFunctionality.TOKEN_AIRDROP;
case TokenCancelAirdrop -> HederaFunctionality.TOKEN_CANCEL_AIRDROP;
case TokenClaimAirdrop -> HederaFunctionality.TOKEN_CLAIM_AIRDROP;
case UNRECOGNIZED -> throw new RuntimeException("Unknown function UNRECOGNIZED");
};
}
Expand Down Expand Up @@ -656,9 +659,6 @@ private static <T extends Record, R extends GeneratedMessageV3> R explicitPbjToP
case MAX_CHILD_RECORDS_EXCEEDED -> ResponseCodeEnum.MAX_CHILD_RECORDS_EXCEEDED;
case INSUFFICIENT_BALANCES_FOR_RENEWAL_FEES -> ResponseCodeEnum.INSUFFICIENT_BALANCES_FOR_RENEWAL_FEES;
case TRANSACTION_HAS_UNKNOWN_FIELDS -> ResponseCodeEnum.TRANSACTION_HAS_UNKNOWN_FIELDS;
case TOKEN_REFERENCE_REPEATED -> ResponseCodeEnum.TOKEN_REFERENCE_REPEATED;
case TOKEN_REFERENCE_LIST_SIZE_LIMIT_EXCEEDED -> ResponseCodeEnum.TOKEN_REFERENCE_LIST_SIZE_LIMIT_EXCEEDED;
case INVALID_OWNER_ID -> ResponseCodeEnum.INVALID_OWNER_ID;
case ACCOUNT_IS_IMMUTABLE -> ResponseCodeEnum.ACCOUNT_IS_IMMUTABLE;
case ALIAS_ALREADY_ASSIGNED -> ResponseCodeEnum.ALIAS_ALREADY_ASSIGNED;
case INVALID_METADATA_KEY -> ResponseCodeEnum.INVALID_METADATA_KEY;
Expand All @@ -681,11 +681,19 @@ private static <T extends Record, R extends GeneratedMessageV3> R explicitPbjToP
case FQDN_SIZE_TOO_LARGE -> ResponseCodeEnum.FQDN_SIZE_TOO_LARGE;
case INVALID_ENDPOINT -> ResponseCodeEnum.INVALID_ENDPOINT;
case GOSSIP_ENDPOINTS_EXCEEDED_LIMIT -> ResponseCodeEnum.GOSSIP_ENDPOINTS_EXCEEDED_LIMIT;
case TOKEN_REFERENCE_REPEATED -> ResponseCodeEnum.TOKEN_REFERENCE_REPEATED;
case INVALID_OWNER_ID -> ResponseCodeEnum.INVALID_OWNER_ID;
case TOKEN_REFERENCE_LIST_SIZE_LIMIT_EXCEEDED -> ResponseCodeEnum.TOKEN_REFERENCE_LIST_SIZE_LIMIT_EXCEEDED;
case SERVICE_ENDPOINTS_EXCEEDED_LIMIT -> ResponseCodeEnum.SERVICE_ENDPOINTS_EXCEEDED_LIMIT;
case INVALID_IPV4_ADDRESS -> ResponseCodeEnum.INVALID_IPV4_ADDRESS;
case EMPTY_TOKEN_REFERENCE_LIST -> ResponseCodeEnum.EMPTY_TOKEN_REFERENCE_LIST;
case UPDATE_NODE_ACCOUNT_NOT_ALLOWED -> ResponseCodeEnum.UPDATE_NODE_ACCOUNT_NOT_ALLOWED;
case TOKEN_HAS_NO_METADATA_OR_SUPPLY_KEY -> ResponseCodeEnum.TOKEN_HAS_NO_METADATA_OR_SUPPLY_KEY;
case PENDING_NFT_AIRDROP_ALREADY_EXISTS -> ResponseCodeEnum.PENDING_NFT_AIRDROP_ALREADY_EXISTS;
case ACCOUNT_HAS_PENDING_AIRDROPS -> ResponseCodeEnum.ACCOUNT_HAS_PENDING_AIRDROPS;
case EMPTY_PENDING_AIRDROP_ID_LIST -> ResponseCodeEnum.EMPTY_PENDING_AIRDROP_ID_LIST;
case PENDING_AIRDROP_ID_REPEATED -> ResponseCodeEnum.PENDING_AIRDROP_ID_REPEATED;
case MAX_PENDING_AIRDROP_ID_EXCEEDED -> ResponseCodeEnum.MAX_PENDING_AIRDROP_ID_EXCEEDED;
case UNRECOGNIZED -> throw new RuntimeException("UNRECOGNIZED Response code!");
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public interface StoreMetricsService {
enum StoreType {
TOPIC,
ACCOUNT,
AIRDROP,
NFT,
TOKEN,
TOKEN_RELATION,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public StoreMetricsServiceImpl(@NonNull final Metrics metrics) {
this.storeMetricsMap = new EnumMap<>(StoreType.class);
storeMetricsMap.put(StoreType.TOPIC, new StoreMetricsImpl(metrics, "topics"));
storeMetricsMap.put(StoreType.ACCOUNT, new StoreMetricsImpl(metrics, "accounts"));
storeMetricsMap.put(StoreType.AIRDROP, new StoreMetricsImpl(metrics, "airdrops"));
storeMetricsMap.put(StoreType.NFT, new StoreMetricsImpl(metrics, "nfts"));
storeMetricsMap.put(StoreType.TOKEN, new StoreMetricsImpl(metrics, "tokens"));
storeMetricsMap.put(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,15 @@
import com.hedera.node.app.service.schedule.ScheduleService;
import com.hedera.node.app.service.schedule.impl.ReadableScheduleStoreImpl;
import com.hedera.node.app.service.token.ReadableAccountStore;
import com.hedera.node.app.service.token.ReadableAirdropStore;
import com.hedera.node.app.service.token.ReadableNetworkStakingRewardsStore;
import com.hedera.node.app.service.token.ReadableNftStore;
import com.hedera.node.app.service.token.ReadableStakingInfoStore;
import com.hedera.node.app.service.token.ReadableTokenRelationStore;
import com.hedera.node.app.service.token.ReadableTokenStore;
import com.hedera.node.app.service.token.TokenService;
import com.hedera.node.app.service.token.impl.ReadableAccountStoreImpl;
import com.hedera.node.app.service.token.impl.ReadableAirdropStoreImpl;
import com.hedera.node.app.service.token.impl.ReadableNetworkStakingRewardsStoreImpl;
import com.hedera.node.app.service.token.impl.ReadableNftStoreImpl;
import com.hedera.node.app.service.token.impl.ReadableStakingInfoStoreImpl;
Expand Down Expand Up @@ -80,6 +82,7 @@ private static Map<Class<?>, StoreEntry> createFactoryMap() {
Map<Class<?>, StoreEntry> newMap = new HashMap<>();
// Tokens and accounts
newMap.put(ReadableAccountStore.class, new StoreEntry(TokenService.NAME, ReadableAccountStoreImpl::new));
newMap.put(ReadableAirdropStore.class, new StoreEntry(TokenService.NAME, ReadableAirdropStoreImpl::new));
newMap.put(ReadableNftStore.class, new StoreEntry(TokenService.NAME, ReadableNftStoreImpl::new));
newMap.put(
ReadableStakingInfoStore.class, new StoreEntry(TokenService.NAME, ReadableStakingInfoStoreImpl::new));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import com.hedera.node.app.service.schedule.impl.WritableScheduleStoreImpl;
import com.hedera.node.app.service.token.TokenService;
import com.hedera.node.app.service.token.impl.WritableAccountStore;
import com.hedera.node.app.service.token.impl.WritableAirdropStore;
import com.hedera.node.app.service.token.impl.WritableNetworkStakingRewardsStore;
import com.hedera.node.app.service.token.impl.WritableNftStore;
import com.hedera.node.app.service.token.impl.WritableStakingInfoStore;
Expand Down Expand Up @@ -70,6 +71,7 @@ private static Map<Class<?>, StoreEntry> createFactoryMap() {
newMap.put(WritableTopicStore.class, new StoreEntry(ConsensusService.NAME, WritableTopicStore::new));
// TokenService
newMap.put(WritableAccountStore.class, new StoreEntry(TokenService.NAME, WritableAccountStore::new));
newMap.put(WritableAirdropStore.class, new StoreEntry(TokenService.NAME, WritableAirdropStore::new));
newMap.put(WritableNftStore.class, new StoreEntry(TokenService.NAME, WritableNftStore::new));
newMap.put(WritableTokenStore.class, new StoreEntry(TokenService.NAME, WritableTokenStore::new));
newMap.put(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,11 @@
import static com.hedera.hapi.node.base.HederaFunctionality.SYSTEM_DELETE;
import static com.hedera.hapi.node.base.HederaFunctionality.SYSTEM_UNDELETE;
import static com.hedera.hapi.node.base.HederaFunctionality.TOKEN_ACCOUNT_WIPE;
import static com.hedera.hapi.node.base.HederaFunctionality.TOKEN_AIRDROP;
import static com.hedera.hapi.node.base.HederaFunctionality.TOKEN_ASSOCIATE_TO_ACCOUNT;
import static com.hedera.hapi.node.base.HederaFunctionality.TOKEN_BURN;
import static com.hedera.hapi.node.base.HederaFunctionality.TOKEN_CANCEL_AIRDROP;
import static com.hedera.hapi.node.base.HederaFunctionality.TOKEN_CLAIM_AIRDROP;
import static com.hedera.hapi.node.base.HederaFunctionality.TOKEN_CREATE;
import static com.hedera.hapi.node.base.HederaFunctionality.TOKEN_DELETE;
import static com.hedera.hapi.node.base.HederaFunctionality.TOKEN_DISSOCIATE_FROM_ACCOUNT;
Expand Down Expand Up @@ -177,6 +180,9 @@
* @param getAccountDetails the permission for {@link HederaFunctionality#GET_ACCOUNT_DETAILS} functionality
* @param tokenUpdateNfts the permission for {@link HederaFunctionality#TOKEN_UPDATE_NFTS} functionality
* @param tokenReject the permission for {@link HederaFunctionality#TOKEN_REJECT} functionality
* @param tokenAirdrop the permission for {@link HederaFunctionality#TOKEN_AIRDROP} functionality
* @param tokenCancelAirdrop the permission for {@link HederaFunctionality#TOKEN_CANCEL_AIRDROP} functionality
* @param tokenClaimAirdrop the permission for {@link HederaFunctionality#TOKEN_CLAIM_AIRDROP} functionality
*
* @param createNode the permission for {@link HederaFunctionality#NODE_CREATE} functionality
* @param updateNode the permission for {@link HederaFunctionality#NODE_UPDATE} functionality
Expand Down Expand Up @@ -248,6 +254,9 @@ public record ApiPermissionConfig(
@ConfigProperty(defaultValue = "2-50") PermissionedAccountsRange getAccountDetails,
@ConfigProperty(defaultValue = "0-*") PermissionedAccountsRange tokenUpdateNfts,
@ConfigProperty(defaultValue = "0-*") PermissionedAccountsRange tokenReject,
@ConfigProperty(defaultValue = "0-*") PermissionedAccountsRange tokenAirdrop,
@ConfigProperty(defaultValue = "0-*") PermissionedAccountsRange tokenCancelAirdrop,
@ConfigProperty(defaultValue = "0-*") PermissionedAccountsRange tokenClaimAirdrop,
@ConfigProperty(defaultValue = "2-55") PermissionedAccountsRange createNode,
@ConfigProperty(defaultValue = "0-*") PermissionedAccountsRange updateNode,
@ConfigProperty(defaultValue = "2-55") PermissionedAccountsRange deleteNode) {
Expand Down Expand Up @@ -298,6 +307,9 @@ public record ApiPermissionConfig(
permissionKeys.put(SCHEDULE_SIGN, c -> c.scheduleSign);
permissionKeys.put(TOKEN_UPDATE_NFTS, c -> c.tokenUpdateNfts);
permissionKeys.put(TOKEN_REJECT, c -> c.tokenReject);
permissionKeys.put(TOKEN_AIRDROP, c -> c.tokenAirdrop);
permissionKeys.put(TOKEN_CANCEL_AIRDROP, c -> c.tokenCancelAirdrop);
permissionKeys.put(TOKEN_CLAIM_AIRDROP, c -> c.tokenClaimAirdrop);
/* Queries */
permissionKeys.put(CONSENSUS_GET_TOPIC_INFO, c -> c.getTopicInfo);
permissionKeys.put(CONTRACT_CALL_LOCAL, c -> c.contractCallLocalMethod);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ public record TokensConfig(
ScaleFactor nftsMintThrottleScaleFactor,
@ConfigProperty(value = "nfts.useVirtualMerkle", defaultValue = "true") @NetworkProperty
boolean nftsUseVirtualMerkle,
@ConfigProperty(value = "maxAllowedAirdrops", defaultValue = "1000000") @NetworkProperty
long maxAllowedAirdrops,
@ConfigProperty(value = "autoCreations.isEnabled", defaultValue = "true") @NetworkProperty
boolean autoCreationsIsEnabled,
@ConfigProperty(value = "maxMetadataBytes", defaultValue = "100") @NetworkProperty int tokensMaxMetadataBytes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,7 @@ protected void givenValidAccount(
tokenAllowances,
2,
false,
null,
null);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ static HederaFunctionality functionalityForType(final DataOneOfType transactionT
case NODE_CREATE -> HederaFunctionality.NODE_CREATE;
case NODE_UPDATE -> HederaFunctionality.NODE_UPDATE;
case NODE_DELETE -> HederaFunctionality.NODE_DELETE;
case TOKEN_CANCEL_AIRDROP -> HederaFunctionality.TOKEN_CANCEL_AIRDROP;
case TOKEN_CLAIM_AIRDROP -> HederaFunctionality.TOKEN_CLAIM_AIRDROP;
case TOKEN_AIRDROP -> HederaFunctionality.TOKEN_AIRDROP;
case UNSET -> HederaFunctionality.NONE;
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright (C) 2024 Hedera Hashgraph, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.hedera.node.app.service.token.impl;

import static com.hedera.node.app.service.token.impl.schemas.V0530TokenSchema.AIRDROPS_KEY;
import static java.util.Objects.requireNonNull;

import com.hedera.hapi.node.base.PendingAirdropId;
import com.hedera.hapi.node.state.token.AccountPendingAirdrop;
import com.hedera.node.app.service.token.ReadableAirdropStore;
import com.swirlds.state.spi.ReadableKVState;
import com.swirlds.state.spi.ReadableStates;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;

/**
* Default implementation of {@link ReadableAirdropStore}
*/
public class ReadableAirdropStoreImpl implements ReadableAirdropStore {
/** The underlying data storage class that holds the airdrop data. */
private final ReadableKVState<PendingAirdropId, AccountPendingAirdrop> readableAirdropState;

/**
* Create a new {@link ReadableAirdropStoreImpl} instance.
*
* @param states The state to use.
*/
public ReadableAirdropStoreImpl(@NonNull final ReadableStates states) {
requireNonNull(states);
this.readableAirdropState = states.get(AIRDROPS_KEY);
}

/** {@inheritDoc} */
@Override
public boolean exists(@NonNull final PendingAirdropId airdropId) {
return readableAirdropState.contains(requireNonNull(airdropId));
}

/** {@inheritDoc} */
@Override
@Nullable
public AccountPendingAirdrop get(@NonNull final PendingAirdropId airdropId) {
requireNonNull(airdropId);
return readableAirdropState.get(airdropId);
}

/** {@inheritDoc} */
@Override
public long sizeOfState() {
return readableAirdropState.size();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.hedera.node.app.service.token.impl.schemas.SyntheticAccountCreator;
import com.hedera.node.app.service.token.impl.schemas.V0490TokenSchema;
import com.hedera.node.app.service.token.impl.schemas.V0500TokenSchema;
import com.hedera.node.app.service.token.impl.schemas.V0530TokenSchema;
import com.swirlds.state.spi.SchemaRegistry;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.time.ZoneId;
Expand All @@ -44,5 +45,6 @@ public void registerSchemas(@NonNull final SchemaRegistry registry) {
requireNonNull(registry);
registry.register(new V0490TokenSchema(new SyntheticAccountCreator()));
registry.register(new V0500TokenSchema());
registry.register(new V0530TokenSchema());
}
}
Loading

0 comments on commit bbf1254

Please sign in to comment.