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

feat: Implement pending state for airdrop purposes #14276

Merged
merged 17 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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-TokenClaimAirdrop"
}

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;
Neeharika-Sompalli marked this conversation as resolved.
Show resolved Hide resolved
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
Loading