Skip to content

Commit

Permalink
cherry pick to 0.39: retire old security model for smart contracts by…
Browse files Browse the repository at this point in the history
… changing HAPI signature-check block limit to LOW

Cherry pick of 666b607

Signed-off-by: David Bakin <117694041+david-bakin-sl@users.noreply.github.com>
  • Loading branch information
david-bakin-sl committed Jun 12, 2023
1 parent 19c1ce0 commit da07d2d
Show file tree
Hide file tree
Showing 76 changed files with 11,373 additions and 8,406 deletions.
Expand Up @@ -61,7 +61,7 @@ balances.compressOnCreation=true
cache.records.ttl=180
contracts.allowAutoAssociations=false
contracts.allowSystemUseOfHapiSigs=TokenAssociateToAccount,TokenDissociateFromAccount,TokenFreezeAccount,TokenUnfreezeAccount,TokenGrantKycToAccount,TokenRevokeKycFromAccount,TokenAccountWipe,TokenBurn,TokenDelete,TokenMint,TokenUnpause,TokenPause,TokenCreate,TokenUpdate,ContractCall,CryptoTransfer
contracts.maxNumWithHapiSigsAccess=10_000_000
contracts.maxNumWithHapiSigsAccess=0
contracts.withSpecialHapiSigsAccess=
contracts.allowCreate2=true
contracts.chainId=295
Expand Down
Expand Up @@ -35,7 +35,7 @@ public record ContractsConfig(
@ConfigProperty(defaultValue = "false") boolean allowAutoAssociations,
// @ConfigProperty(defaultValue =
// "TokenAssociateToAccount,TokenDissociateFromAccount,TokenFreezeAccount,TokenUnfreezeAccount,TokenGrantKycToAccount,TokenRevokeKycFromAccount,TokenAccountWipe,TokenBurn,TokenDelete,TokenMint,TokenUnpause,TokenPause,TokenCreate,TokenUpdate,ContractCall,CryptoTransfer") Set<HederaFunctionality> allowSystemUseOfHapiSigs,
@ConfigProperty(defaultValue = "10000000") long maxNumWithHapiSigsAccess,
@ConfigProperty(defaultValue = "0") long maxNumWithHapiSigsAccess,
// @ConfigProperty(defaultValue = "") Set<Address> withSpecialHapiSigsAccess,
@ConfigProperty(defaultValue = "false") boolean enforceCreationThrottle,
@ConfigProperty(defaultValue = "15000000") long maxGasPerSec,
Expand Down
Expand Up @@ -61,7 +61,7 @@ balances.compressOnCreation=true
cache.records.ttl=180
contracts.allowAutoAssociations=false
contracts.allowSystemUseOfHapiSigs=TokenAssociateToAccount,TokenDissociateFromAccount,TokenFreezeAccount,TokenUnfreezeAccount,TokenGrantKycToAccount,TokenRevokeKycFromAccount,TokenAccountWipe,TokenBurn,TokenDelete,TokenMint,TokenUnpause,TokenPause,TokenCreate,TokenUpdate,ContractCall,CryptoTransfer
contracts.maxNumWithHapiSigsAccess=10_000_000
contracts.maxNumWithHapiSigsAccess=0
contracts.withSpecialHapiSigsAccess=
contracts.allowCreate2=true
contracts.chainId=295
Expand Down
Expand Up @@ -344,7 +344,7 @@ class BootstrapPropertiesTest {
entry(AUTO_RENEW_GRANT_FREE_RENEWALS, false),
entry(CONTRACTS_ALLOW_CREATE2, true),
entry(CONTRACTS_ALLOW_AUTO_ASSOCIATIONS, false),
entry(CONTRACTS_MAX_NUM_WITH_HAPI_SIGS_ACCESS, 10_000_000L),
entry(CONTRACTS_MAX_NUM_WITH_HAPI_SIGS_ACCESS, 0L),
entry(CONTRACTS_WITH_SPECIAL_HAPI_SIGS_ACCESS, Set.<Address>of()),
entry(
CONTRACTS_ALLOW_SYSTEM_USE_OF_HAPI_SIGS,
Expand Down
Expand Up @@ -165,6 +165,7 @@
import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
import java.util.function.Consumer;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.tuweni.bytes.Bytes;
import org.hyperledger.besu.datatypes.Address;
Expand All @@ -177,6 +178,8 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockedStatic;
Expand Down Expand Up @@ -326,6 +329,22 @@ class ERC20PrecompilesTest {
private static final int CENTS_RATE = 12;
private static final int HBAR_RATE = 1;

private enum WithHapiBlockLimit {
LOW,
HIGH
};

private static final Map<WithHapiBlockLimit, Consumer<GlobalDynamicProperties>> setHapiBlockLimitGivens = Map.of(
WithHapiBlockLimit.LOW,
props -> {
given(props.maxNumWithHapiSigsAccess()).willReturn(0L);
},
WithHapiBlockLimit.HIGH,
props -> {
given(props.maxNumWithHapiSigsAccess()).willReturn(Long.MAX_VALUE);
given(props.systemContractsWithTopLevelSigsAccess()).willReturn(Set.of(CryptoTransfer));
});

private HTSPrecompiledContract subject;
private MockedStatic<EntityIdUtils> entityIdUtils;
private MockedStatic<ERCTransferPrecompile> ercTransferPrecompile;
Expand Down Expand Up @@ -1280,15 +1299,14 @@ void transferFrom() throws InvalidProtocolBufferException {
verify(worldUpdater).manageInProgressRecord(recordsHistorian, mockRecordBuilder, mockSynthBodyBuilder);
}

@Test
void transferFromHapiFungible() throws InvalidProtocolBufferException {
@ParameterizedTest
@EnumSource
void transferFromHapiFungible(final WithHapiBlockLimit limit) throws InvalidProtocolBufferException {
final var pretendArguments = Bytes.of(Integers.toBytes(ABI_ID_TRANSFER_FROM));
givenMinimalFrameContext(Bytes.EMPTY);
givenLedgers();
givenPricingUtilsContext();
given(dynamicProperties.maxNumWithHapiSigsAccess()).willReturn(Long.MAX_VALUE);
given(dynamicProperties.systemContractsWithTopLevelSigsAccess()).willReturn(Set.of(CryptoTransfer));

setHapiBlockLimitGivens.get(limit).accept(dynamicProperties);
given(frame.getContractAddress()).willReturn(contractAddr);
given(syntheticTxnFactory.createCryptoTransfer(Collections.singletonList(TOKEN_TRANSFER_FROM_WRAPPER)))
.willReturn(mockSynthBodyBuilder);
Expand Down Expand Up @@ -1354,11 +1372,11 @@ void transferFromHapiFungible() throws InvalidProtocolBufferException {
.build());
}

@Test
void transferFromNFTHapi() throws InvalidProtocolBufferException {
@ParameterizedTest
@EnumSource
void transferFromNFTHapi(final WithHapiBlockLimit limit) throws InvalidProtocolBufferException {
final var pretendArguments = Bytes.of(Integers.toBytes(ABI_ID_TRANSFER_FROM_NFT));
given(dynamicProperties.maxNumWithHapiSigsAccess()).willReturn(Long.MAX_VALUE);
given(dynamicProperties.systemContractsWithTopLevelSigsAccess()).willReturn(Set.of(CryptoTransfer));
setHapiBlockLimitGivens.get(limit).accept(dynamicProperties);
givenMinimalFrameContext(Bytes.EMPTY);
givenLedgers();
givenPricingUtilsContext();
Expand Down Expand Up @@ -1485,12 +1503,13 @@ void transferFails() throws InvalidProtocolBufferException {
assertEquals(invalidFullPrefix, result);
}

@Test
void onlyFallsBackToApprovalWithoutTopLevelSigs() throws InvalidProtocolBufferException {
@ParameterizedTest
@EnumSource
void onlyFallsBackToApprovalWithoutTopLevelSigs(final WithHapiBlockLimit limit)
throws InvalidProtocolBufferException {
final Bytes nestedPretendArguments = Bytes.of(Integers.toBytes(ABI_ID_ERC_TRANSFER));
final Bytes pretendArguments = givenMinimalFrameContext(nestedPretendArguments);
given(dynamicProperties.maxNumWithHapiSigsAccess()).willReturn(Long.MAX_VALUE);
given(dynamicProperties.systemContractsWithTopLevelSigsAccess()).willReturn(Set.of(CryptoTransfer));
setHapiBlockLimitGivens.get(limit).accept(dynamicProperties);
givenLedgers();
givenPricingUtilsContext();

Expand Down
Expand Up @@ -160,9 +160,11 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Consumer;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.tuweni.bytes.Bytes;
import org.hyperledger.besu.datatypes.Address;
Expand All @@ -174,6 +176,8 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
Expand Down Expand Up @@ -316,6 +320,22 @@ class ERC721PrecompilesTest {
private static final int CENTS_RATE = 12;
private static final int HBAR_RATE = 1;

private enum WithHapiBlockLimit {
LOW,
HIGH
};

private static final Map<WithHapiBlockLimit, Consumer<GlobalDynamicProperties>> setHapiBlockLimitGivens = Map.of(
WithHapiBlockLimit.LOW,
props -> {
given(props.maxNumWithHapiSigsAccess()).willReturn(0L);
},
WithHapiBlockLimit.HIGH,
props -> {
given(props.maxNumWithHapiSigsAccess()).willReturn(Long.MAX_VALUE);
given(props.systemContractsWithTopLevelSigsAccess()).willReturn(Set.of(CryptoTransfer));
});

private HTSPrecompiledContract subject;
private MockedStatic<EntityIdUtils> entityIdUtils;
private MockedStatic<IsApprovedForAllPrecompile> isApprovedForAllPrecompile;
Expand Down Expand Up @@ -1280,12 +1300,12 @@ void ownerOfRevertsWithMissingNft() {
assertEquals(missingNftResult, result);
}

@Test
void transferFrom() throws InvalidProtocolBufferException {
@ParameterizedTest
@EnumSource
void transferFrom(final WithHapiBlockLimit limit) throws InvalidProtocolBufferException {
final Bytes nestedPretendArguments = Bytes.of(Integers.toBytes(ABI_ID_ERC_TRANSFER_FROM));
final Bytes pretendArguments = givenMinimalFrameContext(nestedPretendArguments);
given(dynamicProperties.maxNumWithHapiSigsAccess()).willReturn(Long.MAX_VALUE);
given(dynamicProperties.systemContractsWithTopLevelSigsAccess()).willReturn(Set.of(CryptoTransfer));
setHapiBlockLimitGivens.get(limit).accept(dynamicProperties);
givenLedgers();
givenPricingUtilsContext();

Expand Down Expand Up @@ -1362,14 +1382,14 @@ void transferFrom() throws InvalidProtocolBufferException {
verify(frame).addLog(log);
}

@Test
void transferFromFailsForInvalidSig() throws InvalidProtocolBufferException {
@ParameterizedTest
@EnumSource
void transferFromFailsForInvalidSig(final WithHapiBlockLimit limit) throws InvalidProtocolBufferException {
final Bytes nestedPretendArguments = Bytes.of(Integers.toBytes(ABI_ID_ERC_TRANSFER_FROM));
final Bytes pretendArguments = givenMinimalFrameContext(nestedPretendArguments);
givenLedgers();
given(dynamicProperties.maxNumWithHapiSigsAccess()).willReturn(Long.MAX_VALUE);
setHapiBlockLimitGivens.get(limit).accept(dynamicProperties);
givenPricingUtilsContext();
given(dynamicProperties.systemContractsWithTopLevelSigsAccess()).willReturn(Set.of(CryptoTransfer));

given(frame.getContractAddress()).willReturn(contractAddr);
given(syntheticTxnFactory.createCryptoTransfer(Collections.singletonList(nftTransferList)))
Expand Down
Expand Up @@ -170,8 +170,10 @@
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import org.apache.commons.lang3.tuple.Pair;
Expand All @@ -187,6 +189,8 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockedStatic;
Expand Down Expand Up @@ -349,6 +353,22 @@ class TransferPrecompilesTest {
private static final Bytes TRANSFER_NFTS_INPUT = Bytes.fromHexString(
"0x2c4ba191000000000000000000000000000000000000000000000000000000000000047a000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000047700000000000000000000000000000000000000000000000000000000000004770000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000047c000000000000000000000000000000000000000000000010000000000000047c0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000000ea");

private enum WithHapiBlockLimit {
LOW,
HIGH
};

private static final Map<WithHapiBlockLimit, Consumer<GlobalDynamicProperties>> setHapiBlockLimitGivens = Map.of(
WithHapiBlockLimit.LOW,
props -> {
given(props.maxNumWithHapiSigsAccess()).willReturn(0L);
},
WithHapiBlockLimit.HIGH,
props -> {
given(props.maxNumWithHapiSigsAccess()).willReturn(Long.MAX_VALUE);
given(props.systemContractsWithTopLevelSigsAccess()).willReturn(Set.of(CryptoTransfer));
});

private HTSPrecompiledContract subject;
private MockedStatic<TransferPrecompile> transferPrecompile;
final Predicate<AccountID> accoundIdExists = acc -> true;
Expand Down Expand Up @@ -1720,15 +1740,15 @@ void hbarNFTTransferHappyPathWorks() throws InvalidProtocolBufferException {
verify(worldUpdater).manageInProgressRecord(recordsHistorian, mockRecordBuilder, mockSynthBodyBuilder);
}

@Test
void transferFailsAndCatchesProperly() throws InvalidProtocolBufferException {
@ParameterizedTest
@EnumSource
void transferFailsAndCatchesProperly(final WithHapiBlockLimit limit) throws InvalidProtocolBufferException {
final Bytes pretendArguments = Bytes.of(Integers.toBytes(ABI_ID_TRANSFER_TOKEN));

givenMinimalFrameContext();
givenLedgers();
givenPricingUtilsContext();
given(dynamicProperties.maxNumWithHapiSigsAccess()).willReturn(Long.MAX_VALUE);
given(dynamicProperties.systemContractsWithTopLevelSigsAccess()).willReturn(Set.of(CryptoTransfer));
setHapiBlockLimitGivens.get(limit).accept(dynamicProperties);
given(infrastructureFactory.newSideEffects()).willReturn(sideEffects);
given(infrastructureFactory.newImpliedTransfersMarshal(any())).willReturn(impliedTransfersMarshal);
given(worldUpdater.permissivelyUnaliased(any()))
Expand Down
Expand Up @@ -61,7 +61,7 @@ balances.compressOnCreation=true
cache.records.ttl=180
contracts.allowAutoAssociations=false
contracts.allowSystemUseOfHapiSigs=TokenAssociateToAccount,TokenDissociateFromAccount,TokenFreezeAccount,TokenUnfreezeAccount,TokenGrantKycToAccount,TokenRevokeKycFromAccount,TokenAccountWipe,TokenBurn,TokenDelete,TokenMint,TokenUnpause,TokenPause,TokenCreate,TokenUpdate,ContractCall,CryptoTransfer
contracts.maxNumWithHapiSigsAccess=10_000_000
contracts.maxNumWithHapiSigsAccess=0
contracts.withSpecialHapiSigsAccess=
contracts.allowCreate2=true
contracts.chainId=295
Expand Down
Expand Up @@ -61,7 +61,7 @@ balances.compressOnCreation=true
cache.records.ttl=180
contracts.allowAutoAssociations=false
contracts.allowSystemUseOfHapiSigs=TokenAssociateToAccount,TokenDissociateFromAccount,TokenFreezeAccount,TokenUnfreezeAccount,TokenGrantKycToAccount,TokenRevokeKycFromAccount,TokenAccountWipe,TokenBurn,TokenDelete,TokenMint,TokenUnpause,TokenPause,TokenCreate,TokenUpdate,ContractCall,CryptoTransfer
contracts.maxNumWithHapiSigsAccess=10_000_000
contracts.maxNumWithHapiSigsAccess=0
contracts.withSpecialHapiSigsAccess=
contracts.allowCreate2=true
contracts.chainId=295
Expand Down
1 change: 0 additions & 1 deletion hedera-node/test-clients/src/eet/java/EndToEndTests.java
Expand Up @@ -135,7 +135,6 @@ Collection<DynamicContainer> contractPrecompile2() {
new DynamicContainer[] {
// extractSpecsFromSuite(CryptoTransferHTSSuite::new),
// extractSpecsFromSuite(DelegatePrecompileSuite::new),
// extractSpecsFromSuite(DissociatePrecompileSuite::new),
// extractSpecsFromSuite(DynamicGasCostSuite::new),
// extractSpecsFromSuite(MixedHTSPrecompileTestsSuite::new)
});
Expand Down
11 changes: 10 additions & 1 deletion hedera-node/test-clients/src/itest/java/AllIntegrationTests.java
Expand Up @@ -48,11 +48,20 @@
class AllIntegrationTests extends IntegrationTestBase {
private static final String TEST_CONTAINER_NODE0_STREAMS = "build/network/itest/records/node_0";

@Tag("integration")
@Order(0)
@TestFactory
Collection<DynamicContainer> globalPrerequisiteSpecsBySuite() {
return Arrays.stream(SequentialSuites.globalPrerequisiteSuites())
.map(this::extractSpecsFromSuite)
.toList();
}

@Tag("integration")
@Order(1)
@TestFactory
Collection<DynamicContainer> sequentialSpecsBySuite() {
return Arrays.stream(SequentialSuites.all())
return Arrays.stream(SequentialSuites.sequentialSuites())
.map(this::extractSpecsFromSuite)
.toList();
}
Expand Down
3 changes: 0 additions & 3 deletions hedera-node/test-clients/src/itest/java/ConcurrentSuites.java
Expand Up @@ -60,7 +60,6 @@
import com.hedera.services.bdd.suites.contract.precompile.FreezeUnfreezeTokenPrecompileSuite;
import com.hedera.services.bdd.suites.contract.precompile.GrantRevokeKycSuite;
import com.hedera.services.bdd.suites.contract.precompile.LazyCreateThroughPrecompileSuite;
import com.hedera.services.bdd.suites.contract.precompile.MixedHTSPrecompileTestsSuite;
import com.hedera.services.bdd.suites.contract.precompile.PauseUnpauseTokenAccountPrecompileSuite;
import com.hedera.services.bdd.suites.contract.precompile.PrngPrecompileSuite;
import com.hedera.services.bdd.suites.contract.precompile.SigningReqsSuite;
Expand Down Expand Up @@ -179,7 +178,6 @@ static Supplier<HapiSuite>[] all() {
FreezeUnfreezeTokenPrecompileSuite::new,
GrantRevokeKycSuite::new,
LazyCreateThroughPrecompileSuite::new,
MixedHTSPrecompileTestsSuite::new,
PauseUnpauseTokenAccountPrecompileSuite::new,
PrngPrecompileSuite::new,
TokenAndTypeCheckSuite::new,
Expand Down Expand Up @@ -234,7 +232,6 @@ static Supplier<HapiSuite>[] ethereumSuites() {
DefaultTokenStatusSuite::new,
DelegatePrecompileSuite::new,
DeleteTokenPrecompileSuite::new,
DissociatePrecompileSuite::new,
CreatePrecompileSuite::new,
ERCPrecompileSuite::new,
FreezeUnfreezeTokenPrecompileSuite::new,
Expand Down
16 changes: 13 additions & 3 deletions hedera-node/test-clients/src/itest/java/SequentialSuites.java
Expand Up @@ -21,21 +21,31 @@
import com.hedera.services.bdd.suites.leaky.FeatureFlagSuite;
import com.hedera.services.bdd.suites.leaky.LeakyContractTestsSuite;
import com.hedera.services.bdd.suites.leaky.LeakyCryptoTestsSuite;
import com.hedera.services.bdd.suites.leaky.LeakySecurityModelV1Suite;
import com.hedera.services.bdd.suites.regression.TargetNetworkPrep;
import com.hedera.services.bdd.suites.throttling.PrivilegedOpsSuite;
import java.util.function.Supplier;
import org.apache.commons.lang3.ArrayUtils;

public class SequentialSuites {
@SuppressWarnings("unchecked")
static Supplier<HapiSuite>[] all() {
return ArrayUtils.addAll(globalPrerequisiteSuites(), sequentialSuites());
}

@SuppressWarnings("unchecked")
static Supplier<HapiSuite>[] globalPrerequisiteSuites() {
return (Supplier<HapiSuite>[]) new Supplier[] {TargetNetworkPrep::new, FeatureFlagSuite::new};
}

@SuppressWarnings("unchecked")
static Supplier<HapiSuite>[] sequentialSuites() {
return (Supplier<HapiSuite>[]) new Supplier[] {
TargetNetworkPrep::new,
FeatureFlagSuite::new,
SpecialAccountsAreExempted::new,
PrivilegedOpsSuite::new,
TraceabilitySuite::new,
LeakyContractTestsSuite::new,
LeakyCryptoTestsSuite::new,
LeakySecurityModelV1Suite::new,
Create2OperationSuite::new,
};
}
Expand Down

0 comments on commit da07d2d

Please sign in to comment.