mirror of https://github.com/hyperledger/besu
Jumpdest constructor inj (#2821)
Implements caching of JUMP destinations for a contract, fixes #2607 Signed-off-by: Justin Florentine <justin.florentine@consensys.net> Co-authored-by: taccatisid <88524035+taccatisid@users.noreply.github.com> Co-authored-by: Sally MacFarlane <sally.macfarlane@consensys.net> Co-authored-by: Danno Ferrin <danno.ferrin@gmail.com>pull/2846/head
parent
77ac89a4bf
commit
db3a55997b
@ -0,0 +1,56 @@ |
||||
/* |
||||
* Copyright contributors to Hyperledger Besu. |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
|
||||
package org.hyperledger.besu.cli.options.unstable; |
||||
|
||||
import org.hyperledger.besu.cli.options.CLIOptions; |
||||
import org.hyperledger.besu.evm.internal.EvmConfiguration; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.List; |
||||
|
||||
import picocli.CommandLine; |
||||
|
||||
public class EvmOptions implements CLIOptions<EvmConfiguration> { |
||||
|
||||
public static final String JUMPDEST_CACHE_WEIGHT = "--Xevm-jumpdest-cache-weight-kb"; |
||||
|
||||
public static EvmOptions create() { |
||||
return new EvmOptions(); |
||||
} |
||||
|
||||
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) |
||||
@CommandLine.Option( |
||||
names = {JUMPDEST_CACHE_WEIGHT}, |
||||
description = |
||||
"size in kilobytes to allow the cache " |
||||
+ "of valid jump destinations to grow to before evicting the least recently used entry", |
||||
fallbackValue = "32000", |
||||
defaultValue = "32000", |
||||
hidden = true, |
||||
arity = "1") |
||||
private Long jumpDestCacheWeightKilobytes = |
||||
32_000L; // 10k contracts, (25k max contract size / 8 bit) + 32byte hash
|
||||
|
||||
@Override |
||||
public EvmConfiguration toDomainObject() { |
||||
return new EvmConfiguration(jumpDestCacheWeightKilobytes); |
||||
} |
||||
|
||||
@Override |
||||
public List<String> getCLIOptions() { |
||||
return Arrays.asList(JUMPDEST_CACHE_WEIGHT); |
||||
} |
||||
} |
File diff suppressed because one or more lines are too long
@ -0,0 +1,27 @@ |
||||
/* |
||||
* Copyright contributors to Hyperledger Besu. |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
|
||||
package org.hyperledger.besu.evm.internal; |
||||
|
||||
import org.hyperledger.besu.datatypes.Hash; |
||||
|
||||
import com.github.benmanes.caffeine.cache.Weigher; |
||||
|
||||
class CodeScale implements Weigher<Hash, long[]> { |
||||
@Override |
||||
public int weigh(final Hash key, final long[] value) { |
||||
return (value.length * 8) + key.size(); |
||||
} |
||||
} |
@ -0,0 +1,33 @@ |
||||
/* |
||||
* Copyright contributors to Hyperledger Besu. |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
|
||||
package org.hyperledger.besu.evm.internal; |
||||
|
||||
public class EvmConfiguration { |
||||
public static final EvmConfiguration DEFAULT = new EvmConfiguration(32_000L); |
||||
private final long jumpDestCacheWeightKB; |
||||
|
||||
public EvmConfiguration(final long jumpDestCacheWeightKB) { |
||||
this.jumpDestCacheWeightKB = jumpDestCacheWeightKB; |
||||
} |
||||
|
||||
public long getJumpDestCacheWeightBytes() { |
||||
return jumpDestCacheWeightKB * 1024L; |
||||
} |
||||
|
||||
public long getJumpDestCacheWeightKB() { |
||||
return jumpDestCacheWeightKB; |
||||
} |
||||
} |
@ -0,0 +1,62 @@ |
||||
/* |
||||
* Copyright contributors to Hyperledger Besu. |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
|
||||
package org.hyperledger.besu.evm.internal; |
||||
|
||||
import org.hyperledger.besu.datatypes.Hash; |
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache; |
||||
import com.github.benmanes.caffeine.cache.Caffeine; |
||||
|
||||
public class JumpDestCache { |
||||
|
||||
private final Cache<Hash, long[]> cache; |
||||
private final long weightLimit; |
||||
|
||||
public JumpDestCache(final EvmConfiguration config) { |
||||
this(config.getJumpDestCacheWeightBytes()); |
||||
} |
||||
|
||||
private JumpDestCache(final long maxWeightBytes) { |
||||
this.weightLimit = maxWeightBytes; |
||||
this.cache = |
||||
Caffeine.newBuilder().maximumWeight(maxWeightBytes).weigher(new CodeScale()).build(); |
||||
} |
||||
|
||||
public void invalidate(final Hash key) { |
||||
this.cache.invalidate(key); |
||||
} |
||||
|
||||
public void cleanUp() { |
||||
this.cache.cleanUp(); |
||||
} |
||||
|
||||
public long[] getIfPresent(final Hash codeHash) { |
||||
return cache.getIfPresent(codeHash); |
||||
} |
||||
|
||||
public void put(final Hash key, final long[] value) { |
||||
cache.put(key, value); |
||||
} |
||||
|
||||
public long size() { |
||||
cache.cleanUp(); |
||||
return cache.estimatedSize(); |
||||
} |
||||
|
||||
public long getWeightLimit() { |
||||
return weightLimit; |
||||
} |
||||
} |
@ -0,0 +1,42 @@ |
||||
/* |
||||
* Copyright Hyperledger Besu Contributors |
||||
* |
||||
* 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. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
|
||||
package org.hyperledger.besu.evm.internal; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
import org.hyperledger.besu.datatypes.Hash; |
||||
import org.hyperledger.besu.evm.Code; |
||||
import org.hyperledger.besu.evm.operation.JumpDestOperation; |
||||
|
||||
import org.apache.tuweni.bytes.Bytes; |
||||
import org.junit.Test; |
||||
|
||||
public class JumpDestCacheTest { |
||||
|
||||
private final String op = Bytes.of(JumpDestOperation.OPCODE).toUnprefixedHexString(); |
||||
|
||||
@Test |
||||
public void testScale() { |
||||
Bytes contractBytes = |
||||
Bytes.fromHexString("0xDEAD" + op + "BEEF" + op + "B0B0" + op + "C0DE" + op + "FACE"); |
||||
// 3rd bit, 6th bit, 9th bit, 12th bit
|
||||
long[] jumpDests = {4 + 32 + 256 + 2048}; |
||||
CodeScale scale = new CodeScale(); |
||||
Code contractCode = new Code(contractBytes, Hash.hash(contractBytes), jumpDests); |
||||
int weight = scale.weigh(contractCode.getCodeHash(), contractCode.getValidJumpDestinations()); |
||||
assertThat(weight).isEqualTo(contractCode.getCodeHash().size() + jumpDests.length * 8); |
||||
} |
||||
} |
Loading…
Reference in new issue