Skip to content

Commit

Permalink
Merge branch 'refs/heads/develop' into 10828-fix-precision-loss-in-ga…
Browse files Browse the repository at this point in the history
…s-calculation

# Conflicts:
#	hedera-node/hedera-config/src/main/java/com/hedera/node/config/data/ContractsConfig.java
  • Loading branch information
stoyanov-st committed Sep 13, 2024
2 parents 4110fc8 + 5c06347 commit c422486
Show file tree
Hide file tree
Showing 24 changed files with 2,796 additions and 198 deletions.
1 change: 1 addition & 0 deletions hedera-node/configuration/dev/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ balances.exportDir.path=data/accountBalances/
upgrade.artifacts.path=data/upgrade
contracts.chainId=298
contracts.maxGasPerSec=15000000000
contracts.systemContract.tokenInfo.v2.enabled=true
# Needed for end-end tests running on mod-service code
staking.periodMins=1
staking.fees.nodeRewardPercentage=10
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ private ParsingConstants() {
"(" + "string,string,address,string,bool,int64,bool," + TOKEN_KEY + ARRAY_BRACKETS + "," + EXPIRY + ")";
public static final String HEDERA_TOKEN_V3 =
"(" + "string,string,address,string,bool,int64,bool," + TOKEN_KEY + ARRAY_BRACKETS + "," + EXPIRY_V2 + ")";
public static final String HEDERA_TOKEN_V4 = "(" + "string,string,address,string,bool,uint32,bool," + TOKEN_KEY
+ ARRAY_BRACKETS + "," + EXPIRY + ",bytes" + ")";
public static final String TOKEN_INFO = "("
+ HEDERA_TOKEN_V2
+ ",int64,bool,bool,bool,"
Expand Down Expand Up @@ -135,8 +137,11 @@ public enum FunctionType {
HAPI_TRANSFER_FROM_NFT,
HAPI_GET_APPROVED,
HAPI_GET_FUNGIBLE_TOKEN_INFO,
HAPI_GET_FUNGIBLE_TOKEN_INFO_V2,
HAPI_GET_TOKEN_INFO,
HAPI_GET_TOKEN_INFO_V2,
HAPI_GET_NON_FUNGIBLE_TOKEN_INFO,
HAPI_GET_NON_FUNGIBLE_TOKEN_INFO_V2,
HAPI_IS_APPROVED_FOR_ALL,
HAPI_IS_KYC,
GET_TOKEN_DEFAULT_FREEZE_STATUS,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ public record ContractsConfig(
boolean systemContractAccountServiceIsAuthorizedRawEnabled,
@ConfigProperty(value = "systemContract.updateCustomFees.enabled", defaultValue = "true") @NetworkProperty
boolean systemContractUpdateCustomFeesEnabled,
@ConfigProperty(value = "systemContract.tokenInfo.v2.enabled", defaultValue = "false") @NetworkProperty
boolean systemContractTokenInfoV2Enabled,
@ConfigProperty(value = "systemContract.precisionLossFixForGas.enabled", defaultValue = "true") @NetworkProperty
boolean isGasPrecisionLossFixEnabled,
@ConfigProperty(value = "systemContract.canonicalViewGas.enabled", defaultValue = "true") @NetworkProperty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,16 @@ public boolean isSelector(@NonNull final Function... functions) {
return false;
}

/**
* Returns whether this call attempt is a selector for any of the given functions.
* @param function selectors to match against
* @param configEnabled whether the config is enabled
* @return boolean result
*/
public boolean isSelectorIfConfigEnabled(@NonNull final Function function, final boolean configEnabled) {
return configEnabled && isSelector(function);
}

private boolean isRedirectSelector(@NonNull final byte[] functionSelector, @NonNull final byte[] input) {
return Arrays.equals(input, 0, functionSelector.length, functionSelector, 0, functionSelector.length);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,35 @@ private ReturnTypes() {
public static final Fraction ZERO_FRACTION = new Fraction(0, 1);
public static final FixedFee ZERO_FIXED_FEE = new FixedFee(0, null);

// Token info fields
protected static final String TOKEN_FIELDS =
// name, symbol, treasury, memo, tokenSupplyType, maxSupply, freezeDefault
"string,string,address,string,bool,int64,bool,";
protected static final String TOKEN_KEYS = "("
// keyType
+ "uint256,"
// KeyValue
// inheritedAccountKey, contractId, ed25519, ECDSA_secp256k1, delegatableContractId
+ "(bool,address,bytes,bytes,address)"
+ ")[],";
protected static final String EXPIRY_FIELDS =
// second, autoRenewAccount, autoRenewPeriod
"(uint32,address,uint32)";
protected static final String CUSTOM_FEES =
// FixedFee array
// amount, tokenId, useHbarsForPayment, useCurrentTokenForPayment, feeCollector
"(uint32,address,bool,bool,address)[],"
// FractionalFee array
// numerator, denominator, minimumAmount, maximumAmount, netOfTransfers, feeCollector
+ "(uint32,uint32,uint32,uint32,bool,address)[],"
// RoyaltyFee array
// numerator, denominator, amount, tokenId, useHbarsForPayment, feeCollector
+ "(uint32,uint32,uint32,address,bool,address)[]";
protected static final String STATUS_FIELDS =
// totalSupply, deleted, defaultKycStatus, pauseStatus
",int64,bool,bool,bool,";

// Response code types
public static final String INT = "(int)";
public static final String INT_64 = "(int64)";
public static final String INT64_INT64 = "(int64,int64)";
Expand All @@ -76,96 +105,115 @@ private ReturnTypes() {
+ "(bool,address,bytes,bytes,address)" // inheritedAccountKey, contractId, ed25519, ECDSA_secp256k1,
// delegatableContractId
+ ")";

// spotless:off
public static final String RESPONSE_CODE_TOKEN_INFO = "(int32,"
// TokenInfo
+ "("
// HederaToken
+ "("
+ "string,string,address,string,bool,int64,bool," // name, symbol, treasury, memo, tokenSupplyType, maxSupply, freezeDefault
+ TOKEN_FIELDS
// TokenKey array
+ "("
+ "uint256," // keyType
// KeyValue
+ "(bool,address,bytes,bytes,address)" // inheritedAccountKey, contractId, ed25519, ECDSA_secp256k1, delegatableContractId
+ ")[],"
+ TOKEN_KEYS
// Expiry
+ "(uint32,address,uint32)" // second, autoRenewAccount, autoRenewPeriod
+ EXPIRY_FIELDS + ")"
+ STATUS_FIELDS
+ CUSTOM_FEES
+ ",string" // ledgerId
+ ")"
+ ")";

+ ",int64,bool,bool,bool," // totalSupply, deleted, defaultKycStatus, pauseStatus
public static final String RESPONSE_CODE_TOKEN_INFO_V2 = "(int32,"
// TokenInfoV2
+ "("
// HederaTokenV2
+ "("
+ TOKEN_FIELDS
+ TOKEN_KEYS
+ EXPIRY_FIELDS
+ ",bytes" // metadata
+ ")"
+ STATUS_FIELDS // totalSupply, deleted, defaultKycStatus, pauseStatus
+ CUSTOM_FEES
+ ",string" // ledgerId
+ ")"
+ ")";

// FixedFee array
+ "(uint32,address,bool,bool,address)[]," // amount, tokenId, useHbarsForPayment, useCurrentTokenForPayment, feeCollector
// FractionalFee array
+ "(uint32,uint32,uint32,uint32,bool,address)[]," // numerator, denominator, minimumAmount, maximumAmount, netOfTransfers, feeCollector
// RoyaltyFee array
+ "(uint32,uint32,uint32,address,bool,address)[]" // numerator, denominator, amount, tokenId, useHbarsForPayment, feeCollector
+ ",string" // ledgerId
+ ")"
+ ")";
public static final String RESPONSE_CODE_FUNGIBLE_TOKEN_INFO = "(int32,"
// FungibleTokenInfo
+ "("
// TokenInfo
+ "("
// HederaToken
+ "("
+ "string,string,address,string,bool,int64,bool," // name, symbol, treasury, memo, tokenSupplyType, maxSupply, freezeDefault
// TokenKey array
+ "("
+ "uint256," // keyType
// KeyValue
+ "(bool,address,bytes,bytes,address)" // inheritedAccountKey, contractId, ed25519, ECDSA_secp256k1, delegatableContractId
+ ")[],"
// Expiry
+ "(uint32,address,uint32)" // second, autoRenewAccount, autoRenewPeriod
+ ")"
+ TOKEN_FIELDS
+ TOKEN_KEYS
+ EXPIRY_FIELDS + ")"
+ STATUS_FIELDS
+ CUSTOM_FEES
+ ",string" // ledgerId
+ "),"
+ "int32" // decimals
+ ")"
+ ")";

+ ",int64,bool,bool,bool," // totalSupply, deleted, defaultKycStatus, pauseStatus
public static final String RESPONSE_CODE_FUNGIBLE_TOKEN_INFO_V2 = "(int32,"
// FungibleTokenInfoV2
+ "("
// TokenInfoV2
+ "("
// HederaTokenV2
+ "("
+ TOKEN_FIELDS
+ TOKEN_KEYS
+ EXPIRY_FIELDS
+ ",bytes" // metadata
+ ")"
+ STATUS_FIELDS
+ CUSTOM_FEES
+ ",string" // ledgerId
+ "),"
+ "int32" // decimals
+ ")"
+ ")";

// FixedFee array
+ "(uint32,address,bool,bool,address)[]," // amount, tokenId, useHbarsForPayment, useCurrentTokenForPayment, feeCollector
// FractionalFee array
+ "(uint32,uint32,uint32,uint32,bool,address)[]," // numerator, denominator, minimumAmount, maximumAmount, netOfTransfers, feeCollector
// RoyaltyFee array
+ "(uint32,uint32,uint32,address,bool,address)[]" // numerator, denominator, amount, tokenId, useHbarsForPayment, feeCollector
+ ",string" // ledgerId
+ "),"
+ "int32" // decimals
+ ")"
+ ")";
public static final String RESPONSE_CODE_NON_FUNGIBLE_TOKEN_INFO = "(int32,"
// NonFungibleTokenInfo
+ "("
// TokenInfo
+ "("
// HederaToken
+ "("
+ "string,string,address,string,bool,int64,bool," // name, symbol, treasury, memo, tokenSupplyType, maxSupply, freezeDefault
// TokenKey array
+ "("
+ "uint256," // keyType
// KeyValue
+ "(bool,address,bytes,bytes,address)" // inheritedAccountKey, contractId, ed25519, ECDSA_secp256k1, delegatableContractId
+ ")[],"
// Expiry
+ "(uint32,address,uint32)" // second, autoRenewAccount, autoRenewPeriod
+ ")"

+ ",int64,bool,bool,bool," // totalSupply, deleted, defaultKycStatus, pauseStatus
+ TOKEN_FIELDS
+ TOKEN_KEYS
+ EXPIRY_FIELDS + ")"
+ STATUS_FIELDS
+ CUSTOM_FEES
+ ",string" // ledgerId
+ "),"
+ "int64,address,int64,bytes,address" // serialNumber, ownerId, creationTime, metadata, spenderId
+ ")"
+ ")";

// FixedFee array
+ "(uint32,address,bool,bool,address)[]," // amount, tokenId, useHbarsForPayment, useCurrentTokenForPayment, feeCollector
// FractionalFee array
+ "(uint32,uint32,uint32,uint32,bool,address)[]," // numerator, denominator, minimumAmount, maximumAmount, netOfTransfers, feeCollector
// RoyaltyFee array
+ "(uint32,uint32,uint32,address,bool,address)[]" // numerator, denominator, amount, tokenId, useHbarsForPayment, feeCollector
+ ",string" // ledgerId
+ "),"
+ "int64,address,int64,bytes,address" // serialNumber, ownerId, creationTime, metadata, spenderId
+ ")"
+ ")";
public static final String RESPONSE_CODE_NON_FUNGIBLE_TOKEN_INFO_V2 = "(int32,"
// NonFungibleTokenInfoV2
+ "("
// TokenInfoV2
+ "("
// HederaTokenV2
+ "("
+ TOKEN_FIELDS
+ TOKEN_KEYS
+ EXPIRY_FIELDS
+ ",bytes" // metadata
+ ")"
+ STATUS_FIELDS // totalSupply, deleted, defaultKycStatus, pauseStatus
+ CUSTOM_FEES
+ ",string" // ledgerId
+ "),"
+ "int64,address,int64,bytes,address" // serialNumber, ownerId, creationTime, metadata, spenderId
+ ")"
+ ")";

public static final String RESPONSE_CODE_CUSTOM_FEES = "(int32,"
// FixedFee array
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,13 +181,15 @@ private static List<Tuple> royaltyFeesTupleListFor(@NonNull final Token token) {
* @return Tuple encoding of the TokenInfo
*/
@NonNull
public static Tuple tokenInfoTupleFor(@NonNull final Token token, @NonNull final String ledgerId) {
public static Tuple tokenInfoTupleFor(@NonNull final Token token, @NonNull final String ledgerId, int version) {
final var fixedFees = fixedFeesTupleListFor(token);
final var fractionalFees = fractionalFeesTupleListFor(token);
final var royaltyFees = royaltyFeesTupleListFor(token);

final var hederaToken = version == 1 ? hederaTokenTupleFor(token) : hederaTokenTupleForV2(token);

return Tuple.of(
hederaTokenTupleFor(token),
hederaToken,
token.totalSupply(),
token.deleted(),
token.accountsKycGrantedByDefault(),
Expand All @@ -205,8 +207,9 @@ public static Tuple tokenInfoTupleFor(@NonNull final Token token, @NonNull final
* @return Tuple encoding of the FungibleTokenInfo
*/
@NonNull
public static Tuple fungibleTokenInfoTupleFor(@NonNull final Token token, @NonNull final String ledgerId) {
return Tuple.of(tokenInfoTupleFor(token, ledgerId), token.decimals());
public static Tuple fungibleTokenInfoTupleFor(
@NonNull final Token token, @NonNull final String ledgerId, int version) {
return Tuple.of(tokenInfoTupleFor(token, ledgerId, version), token.decimals());
}

/**
Expand All @@ -220,15 +223,16 @@ public static Tuple nftTokenInfoTupleFor(
@NonNull final Nft nft,
final long serialNumber,
@NonNull final String ledgerId,
@NonNull final HederaNativeOperations nativeOperations) {
@NonNull final HederaNativeOperations nativeOperations,
int version) {
requireNonNull(nft);
requireNonNull(token);
requireNonNull(ledgerId);
requireNonNull(nativeOperations);

final var nftMetaData = nft.metadata() != null ? nft.metadata().toByteArray() : Bytes.EMPTY.toByteArray();
return Tuple.of(
tokenInfoTupleFor(token, ledgerId),
tokenInfoTupleFor(token, ledgerId, version),
serialNumber,
// The odd construct allowing a token to not have a treasury account set is to accommodate
// Token.DEFAULT being passed into this method, which a few Call implementations do
Expand Down Expand Up @@ -273,17 +277,6 @@ public static Tuple typedKeyTupleFor(@NonNull final BigInteger keyType, @NonNull
*/
@NonNull
private static Tuple hederaTokenTupleFor(@NonNull final Token token) {
//
final Tuple[] keyList = {
typedKeyTupleFor(TokenKeyType.ADMIN_KEY.bigIntegerValue(), token.adminKeyOrElse(Key.DEFAULT)),
typedKeyTupleFor(TokenKeyType.KYC_KEY.bigIntegerValue(), token.kycKeyOrElse(Key.DEFAULT)),
typedKeyTupleFor(TokenKeyType.FREEZE_KEY.bigIntegerValue(), token.freezeKeyOrElse(Key.DEFAULT)),
typedKeyTupleFor(TokenKeyType.WIPE_KEY.bigIntegerValue(), token.wipeKeyOrElse(Key.DEFAULT)),
typedKeyTupleFor(TokenKeyType.SUPPLY_KEY.bigIntegerValue(), token.supplyKeyOrElse(Key.DEFAULT)),
typedKeyTupleFor(TokenKeyType.FEE_SCHEDULE_KEY.bigIntegerValue(), token.feeScheduleKeyOrElse(Key.DEFAULT)),
typedKeyTupleFor(TokenKeyType.PAUSE_KEY.bigIntegerValue(), token.pauseKeyOrElse(Key.DEFAULT))
};

return Tuple.of(
token.name(),
token.symbol(),
Expand All @@ -292,18 +285,53 @@ private static Tuple hederaTokenTupleFor(@NonNull final Token token) {
token.supplyType().protoOrdinal() == TokenSupplyType.FINITE_VALUE,
token.maxSupply(),
token.accountsFrozenByDefault(),
keyList,
prepareKeyList(token, false),
expiryTupleFor(token));
}

private static Tuple[] prepareKeyList(@NonNull final Token token, final boolean isV2) {
final var keyList = new java.util.ArrayList<>(List.of(
typedKeyTupleFor(TokenKeyType.ADMIN_KEY.bigIntegerValue(), token.adminKeyOrElse(Key.DEFAULT)),
typedKeyTupleFor(TokenKeyType.KYC_KEY.bigIntegerValue(), token.kycKeyOrElse(Key.DEFAULT)),
typedKeyTupleFor(TokenKeyType.FREEZE_KEY.bigIntegerValue(), token.freezeKeyOrElse(Key.DEFAULT)),
typedKeyTupleFor(TokenKeyType.WIPE_KEY.bigIntegerValue(), token.wipeKeyOrElse(Key.DEFAULT)),
typedKeyTupleFor(TokenKeyType.SUPPLY_KEY.bigIntegerValue(), token.supplyKeyOrElse(Key.DEFAULT)),
typedKeyTupleFor(
TokenKeyType.FEE_SCHEDULE_KEY.bigIntegerValue(), token.feeScheduleKeyOrElse(Key.DEFAULT)),
typedKeyTupleFor(TokenKeyType.PAUSE_KEY.bigIntegerValue(), token.pauseKeyOrElse(Key.DEFAULT))));
if (isV2) {
keyList.add(typedKeyTupleFor(
TokenKeyType.METADATA_KEY.bigIntegerValue(), token.metadataKeyOrElse(Key.DEFAULT)));
}
return keyList.toArray(Tuple[]::new);
}

@NonNull
private static Tuple hederaTokenTupleForV2(@NonNull final Token token) {
final var tokenMetaData =
token.metadata().length() > 0 ? token.metadata().toByteArray() : Bytes.EMPTY.toByteArray();
return Tuple.of(
token.name(),
token.symbol(),
headlongAddressOf(token.treasuryAccountIdOrElse(ZERO_ACCOUNT_ID)),
token.memo(),
token.supplyType().protoOrdinal() == TokenSupplyType.FINITE_VALUE,
token.maxSupply(),
token.accountsFrozenByDefault(),
prepareKeyList(token, true),
expiryTupleFor(token),
tokenMetaData);
}

public enum TokenKeyType {
ADMIN_KEY(1),
KYC_KEY(2),
FREEZE_KEY(4),
WIPE_KEY(8),
SUPPLY_KEY(16),
FEE_SCHEDULE_KEY(32),
PAUSE_KEY(64);
PAUSE_KEY(64),
METADATA_KEY(128);

private final int value;

Expand Down
Loading

0 comments on commit c422486

Please sign in to comment.