mirror of https://github.com/hyperledger/besu
Remove EIP-3074 code (#7208)
Remove all EIP-3074 code from Besu. Since EIP-3074 has been replaced with EIP-7702 in Pectra, and there is no intent to schedule it for a future fork there is no need to retain the code. Signed-off-by: Danno Ferrin <danno@numisight.com>revert-7203-patch-1
parent
8a8f1ce712
commit
365737c2eb
@ -1,102 +0,0 @@ |
||||
/* |
||||
* 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.operation; |
||||
|
||||
import static org.hyperledger.besu.evm.internal.Words.clampedToLong; |
||||
|
||||
import org.hyperledger.besu.datatypes.Address; |
||||
import org.hyperledger.besu.datatypes.Wei; |
||||
import org.hyperledger.besu.evm.EVM; |
||||
import org.hyperledger.besu.evm.frame.ExceptionalHaltReason; |
||||
import org.hyperledger.besu.evm.frame.MessageFrame; |
||||
import org.hyperledger.besu.evm.gascalculator.GasCalculator; |
||||
import org.hyperledger.besu.evm.internal.Words; |
||||
|
||||
import org.apache.tuweni.bytes.Bytes32; |
||||
|
||||
/** Introduced via EIP-3074 to call another contract with a different authorization context. */ |
||||
public class AuthCallOperation extends AbstractCallOperation { |
||||
|
||||
/** |
||||
* Instantiates a new AuthCallOperation. |
||||
* |
||||
* @param gasCalculator a Prague or later gas calculator |
||||
*/ |
||||
public AuthCallOperation(final GasCalculator gasCalculator) { |
||||
super(0xF7, "AUTHCALL", 7, 1, gasCalculator); |
||||
} |
||||
|
||||
@Override |
||||
protected Address to(final MessageFrame frame) { |
||||
return Words.toAddress(frame.getStackItem(1)); |
||||
} |
||||
|
||||
@Override |
||||
protected Wei value(final MessageFrame frame) { |
||||
return Wei.wrap(frame.getStackItem(2)); |
||||
} |
||||
|
||||
@Override |
||||
protected Wei apparentValue(final MessageFrame frame) { |
||||
return value(frame); |
||||
} |
||||
|
||||
@Override |
||||
protected long inputDataOffset(final MessageFrame frame) { |
||||
return clampedToLong(frame.getStackItem(3)); |
||||
} |
||||
|
||||
@Override |
||||
protected long inputDataLength(final MessageFrame frame) { |
||||
return clampedToLong(frame.getStackItem(4)); |
||||
} |
||||
|
||||
@Override |
||||
protected long outputDataOffset(final MessageFrame frame) { |
||||
return clampedToLong(frame.getStackItem(5)); |
||||
} |
||||
|
||||
@Override |
||||
protected long outputDataLength(final MessageFrame frame) { |
||||
return clampedToLong(frame.getStackItem(6)); |
||||
} |
||||
|
||||
@Override |
||||
protected Address address(final MessageFrame frame) { |
||||
return to(frame); |
||||
} |
||||
|
||||
@Override |
||||
protected Address sender(final MessageFrame frame) { |
||||
return frame.getAuthorizedBy(); |
||||
} |
||||
|
||||
@Override |
||||
public long gasAvailableForChildCall(final MessageFrame frame) { |
||||
return gasCalculator().gasAvailableForChildCall(frame, gas(frame), !value(frame).isZero()); |
||||
} |
||||
|
||||
@Override |
||||
public OperationResult execute(final MessageFrame frame, final EVM evm) { |
||||
if (frame.isStatic() && !value(frame).isZero()) { |
||||
return new OperationResult(cost(frame, true), ExceptionalHaltReason.ILLEGAL_STATE_CHANGE); |
||||
} else if (frame.getAuthorizedBy() != null) { |
||||
return super.execute(frame, evm); |
||||
} else { |
||||
frame.pushStackItem(Bytes32.ZERO); |
||||
return new OperationResult(cost(frame, true), null); |
||||
} |
||||
} |
||||
} |
@ -1,118 +0,0 @@ |
||||
/* |
||||
* 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.operation; |
||||
|
||||
import static org.hyperledger.besu.evm.internal.Words.clampedToLong; |
||||
|
||||
import org.hyperledger.besu.crypto.Hash; |
||||
import org.hyperledger.besu.crypto.SECPPublicKey; |
||||
import org.hyperledger.besu.crypto.SECPSignature; |
||||
import org.hyperledger.besu.crypto.SignatureAlgorithm; |
||||
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; |
||||
import org.hyperledger.besu.datatypes.Address; |
||||
import org.hyperledger.besu.evm.EVM; |
||||
import org.hyperledger.besu.evm.account.Account; |
||||
import org.hyperledger.besu.evm.frame.ExceptionalHaltReason; |
||||
import org.hyperledger.besu.evm.frame.MessageFrame; |
||||
import org.hyperledger.besu.evm.gascalculator.GasCalculator; |
||||
import org.hyperledger.besu.evm.internal.Words; |
||||
|
||||
import java.util.Optional; |
||||
|
||||
import org.apache.tuweni.bytes.Bytes; |
||||
import org.apache.tuweni.bytes.Bytes32; |
||||
import org.apache.tuweni.units.bigints.UInt256; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** The AUTH operation. */ |
||||
public class AuthOperation extends AbstractOperation { |
||||
|
||||
/** The constant MAGIC defined by EIP-3074 */ |
||||
public static final byte MAGIC = 0x4; |
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AuthOperation.class); |
||||
|
||||
private static final SignatureAlgorithm signatureAlgorithm = |
||||
SignatureAlgorithmFactory.getInstance(); |
||||
|
||||
/** |
||||
* Instantiates a new AuthOperation. |
||||
* |
||||
* @param gasCalculator a Prague or later gas calculator |
||||
*/ |
||||
public AuthOperation(final GasCalculator gasCalculator) { |
||||
super(0xF6, "AUTH", 3, 1, gasCalculator); |
||||
} |
||||
|
||||
@Override |
||||
public OperationResult execute(final MessageFrame frame, final EVM evm) { |
||||
// create authority from stack
|
||||
Address authority = Words.toAddress(frame.getStackItem(0)); |
||||
long offset = clampedToLong(frame.getStackItem(1)); |
||||
long length = clampedToLong(frame.getStackItem(2)); |
||||
|
||||
final long gasCost = |
||||
super.gasCalculator().authOperationGasCost(frame, offset, length, authority); |
||||
if (frame.getRemainingGas() < gasCost) { |
||||
return new OperationResult(gasCost, ExceptionalHaltReason.INSUFFICIENT_GAS); |
||||
} |
||||
|
||||
byte yParity = frame.readMemory(offset, 1).get(0); |
||||
Bytes32 r = Bytes32.wrap(frame.readMemory(offset + 1, 32)); |
||||
Bytes32 s = Bytes32.wrap(frame.readMemory(offset + 33, 32)); |
||||
Bytes32 commit = Bytes32.wrap(frame.readMemory(offset + 65, 32)); |
||||
Bytes32 invoker = Bytes32.leftPad(frame.getContractAddress()); |
||||
// TODO add test for getting sender nonce when account does not exist
|
||||
Bytes32 senderNonce = |
||||
Bytes32.leftPad( |
||||
Bytes.ofUnsignedLong( |
||||
Optional.ofNullable(frame.getWorldUpdater().getAccount(authority)) |
||||
.map(Account::getNonce) |
||||
.orElse(0L))); |
||||
if (evm.getChainId().isEmpty()) { |
||||
frame.pushStackItem(UInt256.ZERO); |
||||
LOG.error("ChainId is not set"); |
||||
return new OperationResult(0, null); |
||||
} |
||||
Bytes authPreImage = |
||||
Bytes.concatenate( |
||||
Bytes.ofUnsignedShort(MAGIC), evm.getChainId().get(), senderNonce, invoker, commit); |
||||
Bytes32 messageHash = Hash.keccak256(authPreImage); |
||||
Optional<SECPPublicKey> publicKey; |
||||
try { |
||||
SECPSignature signature = |
||||
signatureAlgorithm.createSignature( |
||||
r.toUnsignedBigInteger(), s.toUnsignedBigInteger(), yParity); |
||||
publicKey = signatureAlgorithm.recoverPublicKeyFromSignature(messageHash, signature); |
||||
} catch (IllegalArgumentException e) { |
||||
|
||||
frame.pushStackItem(UInt256.ZERO); |
||||
return new OperationResult(gasCost, null); |
||||
} |
||||
if (publicKey.isPresent()) { |
||||
Address signerAddress = Address.extract(publicKey.get()); |
||||
if (signerAddress.equals(authority)) { |
||||
frame.setAuthorizedBy(authority); |
||||
frame.pushStackItem(UInt256.ONE); |
||||
} else { |
||||
frame.pushStackItem(UInt256.ZERO); |
||||
} |
||||
} else { |
||||
frame.pushStackItem(UInt256.ZERO); |
||||
} |
||||
return new OperationResult(gasCost, null); |
||||
} |
||||
} |
@ -1,153 +0,0 @@ |
||||
/* |
||||
* 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.operations; |
||||
|
||||
import static org.mockito.Mockito.mock; |
||||
import static org.mockito.Mockito.never; |
||||
import static org.mockito.Mockito.verify; |
||||
import static org.mockito.Mockito.when; |
||||
|
||||
import org.hyperledger.besu.crypto.Hash; |
||||
import org.hyperledger.besu.crypto.KeyPair; |
||||
import org.hyperledger.besu.crypto.SECPSignature; |
||||
import org.hyperledger.besu.crypto.SignatureAlgorithm; |
||||
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; |
||||
import org.hyperledger.besu.datatypes.Address; |
||||
import org.hyperledger.besu.evm.EVM; |
||||
import org.hyperledger.besu.evm.account.MutableAccount; |
||||
import org.hyperledger.besu.evm.frame.MessageFrame; |
||||
import org.hyperledger.besu.evm.gascalculator.PragueGasCalculator; |
||||
import org.hyperledger.besu.evm.operation.AuthOperation; |
||||
import org.hyperledger.besu.evm.worldstate.WorldUpdater; |
||||
|
||||
import java.util.Optional; |
||||
|
||||
import org.apache.tuweni.bytes.Bytes; |
||||
import org.apache.tuweni.bytes.Bytes32; |
||||
import org.apache.tuweni.units.bigints.UInt256; |
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
public class AuthOperationTest { |
||||
|
||||
@Test |
||||
public void testAuthOperation() { |
||||
SignatureAlgorithm algo = SignatureAlgorithmFactory.getInstance(); |
||||
KeyPair keys = algo.generateKeyPair(); |
||||
Address authingAddress = Address.extract(keys.getPublicKey()); |
||||
EVM fakeEVM = mock(EVM.class); |
||||
|
||||
Optional<Bytes> chainId = Optional.of(Bytes.of(1)); |
||||
when(fakeEVM.getChainId()).thenReturn(chainId); |
||||
long senderNonce = 0; |
||||
Address invokerAddress = Address.fromHexString("0xdeadbeef"); |
||||
Bytes32 invoker = Bytes32.leftPad(invokerAddress); |
||||
Bytes32 contractCommitment = Bytes32.leftPad(Bytes.fromHexString("0x1234")); |
||||
Bytes authPreImage = |
||||
Bytes.concatenate( |
||||
Bytes.ofUnsignedShort(AuthOperation.MAGIC), |
||||
chainId.get(), |
||||
Bytes32.leftPad(Bytes.ofUnsignedLong(senderNonce)), |
||||
invoker, |
||||
contractCommitment); |
||||
Bytes32 messageHash = Hash.keccak256(authPreImage); |
||||
SECPSignature signature = algo.sign(messageHash, keys); |
||||
|
||||
MessageFrame frame = mock(MessageFrame.class); |
||||
when(frame.getContractAddress()).thenReturn(invokerAddress); |
||||
MutableAccount authingAccount = mock(MutableAccount.class); |
||||
when(authingAccount.getAddress()).thenReturn(authingAddress); |
||||
when(authingAccount.getNonce()).thenReturn(senderNonce); |
||||
when(frame.getRemainingGas()).thenReturn(1000000L); |
||||
WorldUpdater state = mock(WorldUpdater.class); |
||||
|
||||
when(state.getAccount(authingAddress)).thenReturn(authingAccount); |
||||
|
||||
when(frame.getWorldUpdater()).thenReturn(state); |
||||
|
||||
when(frame.getSenderAddress()).thenReturn(authingAddress); |
||||
when(state.getSenderAccount(frame)).thenReturn(authingAccount); |
||||
when(frame.getStackItem(0)).thenReturn(authingAddress); |
||||
when(frame.getStackItem(1)).thenReturn(Bytes.of(0)); |
||||
when(frame.getStackItem(2)).thenReturn(Bytes.of(97)); |
||||
Bytes encodedSignature = signature.encodedBytes(); |
||||
when(frame.readMemory(0, 1)).thenReturn(encodedSignature.slice(64, 1)); |
||||
when(frame.readMemory(1, 32)).thenReturn(Bytes32.wrap(encodedSignature.slice(0, 32).toArray())); |
||||
when(frame.readMemory(33, 32)) |
||||
.thenReturn(Bytes32.wrap(encodedSignature.slice(32, 32).toArray())); |
||||
when(frame.readMemory(65, 32)).thenReturn(contractCommitment); |
||||
|
||||
AuthOperation authOperation = new AuthOperation(new PragueGasCalculator()); |
||||
authOperation.execute(frame, fakeEVM); |
||||
verify(frame).setAuthorizedBy(authingAddress); |
||||
verify(frame).pushStackItem(UInt256.ONE); |
||||
} |
||||
|
||||
@Test |
||||
public void testAuthOperationNegative() { |
||||
SignatureAlgorithm algo = SignatureAlgorithmFactory.getInstance(); |
||||
KeyPair keys = algo.generateKeyPair(); |
||||
Address authingAddress = Address.extract(keys.getPublicKey()); |
||||
EVM fakeEVM = mock(EVM.class); |
||||
|
||||
Optional<Bytes> chainId = Optional.of(Bytes.of(1)); |
||||
when(fakeEVM.getChainId()).thenReturn(chainId); |
||||
long senderNonce = 0; |
||||
Address invokerAddress = Address.fromHexString("0xdeadbeef"); |
||||
Bytes32 invoker = Bytes32.leftPad(invokerAddress); |
||||
Bytes32 contractCommitment = Bytes32.leftPad(Bytes.fromHexString("0x1234")); |
||||
Bytes authPreImage = |
||||
Bytes.concatenate( |
||||
Bytes.ofUnsignedShort(AuthOperation.MAGIC), |
||||
chainId.get(), |
||||
Bytes32.leftPad(Bytes.ofUnsignedLong(senderNonce)), |
||||
invoker, |
||||
contractCommitment); |
||||
Bytes32 messageHash = Hash.keccak256(authPreImage); |
||||
|
||||
// Generate a new key pair to create an incorrect signature
|
||||
KeyPair wrongKeys = algo.generateKeyPair(); |
||||
SECPSignature wrongSignature = algo.sign(messageHash, wrongKeys); |
||||
|
||||
MessageFrame frame = mock(MessageFrame.class); |
||||
when(frame.getRemainingGas()).thenReturn(1000000L); |
||||
when(frame.getContractAddress()).thenReturn(invokerAddress); |
||||
MutableAccount authingAccount = mock(MutableAccount.class); |
||||
when(authingAccount.getAddress()).thenReturn(authingAddress); |
||||
when(authingAccount.getNonce()).thenReturn(senderNonce); |
||||
|
||||
WorldUpdater state = mock(WorldUpdater.class); |
||||
|
||||
when(state.getAccount(authingAddress)).thenReturn(authingAccount); |
||||
|
||||
when(frame.getWorldUpdater()).thenReturn(state); |
||||
|
||||
when(frame.getSenderAddress()).thenReturn(authingAddress); |
||||
when(state.getSenderAccount(frame)).thenReturn(authingAccount); |
||||
when(frame.getStackItem(0)).thenReturn(authingAddress); |
||||
when(frame.getStackItem(1)).thenReturn(Bytes.of(0)); |
||||
when(frame.getStackItem(2)).thenReturn(Bytes.of(97)); |
||||
Bytes encodedSignature = wrongSignature.encodedBytes(); // Use the wrong signature
|
||||
when(frame.readMemory(0, 1)).thenReturn(encodedSignature.slice(64, 1)); |
||||
when(frame.readMemory(1, 32)).thenReturn(Bytes32.wrap(encodedSignature.slice(0, 32).toArray())); |
||||
when(frame.readMemory(33, 32)) |
||||
.thenReturn(Bytes32.wrap(encodedSignature.slice(32, 32).toArray())); |
||||
when(frame.readMemory(65, 32)).thenReturn(contractCommitment); |
||||
|
||||
AuthOperation authOperation = new AuthOperation(new PragueGasCalculator()); |
||||
authOperation.execute(frame, fakeEVM); |
||||
verify(frame, never()).setAuthorizedBy(authingAddress); // The address should not be authorized
|
||||
verify(frame).pushStackItem(UInt256.ZERO); // The stack should contain UInt256.ZERO
|
||||
} |
||||
} |
@ -1,152 +0,0 @@ |
||||
/* |
||||
* 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.processor; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.mockito.ArgumentMatchers.any; |
||||
import static org.mockito.Mockito.spy; |
||||
import static org.mockito.Mockito.times; |
||||
import static org.mockito.Mockito.verify; |
||||
|
||||
import org.hyperledger.besu.crypto.Hash; |
||||
import org.hyperledger.besu.crypto.KeyPair; |
||||
import org.hyperledger.besu.crypto.SECPSignature; |
||||
import org.hyperledger.besu.crypto.SignatureAlgorithm; |
||||
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; |
||||
import org.hyperledger.besu.datatypes.Address; |
||||
import org.hyperledger.besu.datatypes.Wei; |
||||
import org.hyperledger.besu.evm.EVM; |
||||
import org.hyperledger.besu.evm.MainnetEVMs; |
||||
import org.hyperledger.besu.evm.fluent.EVMExecutor; |
||||
import org.hyperledger.besu.evm.frame.MessageFrame; |
||||
import org.hyperledger.besu.evm.gascalculator.PragueGasCalculator; |
||||
import org.hyperledger.besu.evm.internal.EvmConfiguration; |
||||
import org.hyperledger.besu.evm.operation.AuthOperation; |
||||
import org.hyperledger.besu.evm.toy.ToyWorld; |
||||
import org.hyperledger.besu.evm.worldstate.WorldUpdater; |
||||
|
||||
import java.math.BigInteger; |
||||
import java.util.List; |
||||
import java.util.Optional; |
||||
|
||||
import org.apache.tuweni.bytes.Bytes; |
||||
import org.apache.tuweni.bytes.Bytes32; |
||||
import org.junit.jupiter.api.Test; |
||||
import org.mockito.ArgumentCaptor; |
||||
|
||||
public class AuthCallProcessorTest extends MessageCallProcessorTest { |
||||
|
||||
MessageCallProcessor spyingMessageCallProcessor; |
||||
ArgumentCaptor<MessageFrame> frameCaptor = ArgumentCaptor.forClass(MessageFrame.class); |
||||
|
||||
WorldUpdater toyWorld = new ToyWorld(); |
||||
|
||||
@Test |
||||
public void authCallHappyPath() { |
||||
final EVM pragueEVM = |
||||
MainnetEVMs.prague(new PragueGasCalculator(), BigInteger.ONE, EvmConfiguration.DEFAULT); |
||||
final EVMExecutor executor = EVMExecutor.evm(pragueEVM); |
||||
this.spyingMessageCallProcessor = |
||||
spy(new MessageCallProcessor(pragueEVM, precompileContractRegistry)); |
||||
executor.messageCallProcessor(this.spyingMessageCallProcessor); |
||||
|
||||
executor.worldUpdater(toyWorld); |
||||
executor.gas(10_000_000_000L); |
||||
|
||||
SignatureAlgorithm algo = SignatureAlgorithmFactory.getInstance(); |
||||
KeyPair keys = algo.generateKeyPair(); |
||||
Optional<Bytes> chainId = Optional.of(Bytes.of(1)); |
||||
long senderNonce = 0; |
||||
Address invokerAddress = Address.fromHexString("0xdeadbeef"); |
||||
Bytes32 invoker = Bytes32.leftPad(invokerAddress); |
||||
Bytes32 contractCommitment = Bytes32.leftPad(Bytes.fromHexString("0x1234")); |
||||
Bytes authPreImage = |
||||
Bytes.concatenate( |
||||
Bytes.ofUnsignedShort(AuthOperation.MAGIC), |
||||
Bytes32.leftPad(chainId.get()), |
||||
Bytes32.leftPad(Bytes.ofUnsignedLong(senderNonce)), |
||||
invoker, |
||||
contractCommitment); |
||||
Bytes32 messageHash = Hash.keccak256(authPreImage); |
||||
SECPSignature signature = algo.sign(messageHash, keys); |
||||
Bytes encodedSignature = signature.encodedBytes(); |
||||
|
||||
Bytes authParam = |
||||
Bytes.concatenate( |
||||
encodedSignature.slice(64, 1), // y parity
|
||||
encodedSignature.slice(0, 32), // r
|
||||
encodedSignature.slice(32, 32), // s
|
||||
contractCommitment); |
||||
|
||||
toyWorld.createAccount( |
||||
Address.extract(keys.getPublicKey()), 0, Wei.MAX_WEI); // initialize authority account
|
||||
toyWorld.createAccount(invokerAddress, 0, Wei.MAX_WEI); // initialize invoker account
|
||||
final Bytes codeBytes = |
||||
Bytes.fromHexString( |
||||
"0x" |
||||
+ "6061" // push 97 the calldata length
|
||||
+ "6000" // push 0 the offset
|
||||
+ "6000" // push 0 the destination offset
|
||||
+ "37" // calldatacopy 97 bytes of the auth param to mem 0
|
||||
+ "6061" // param is 97 bytes (0x61)
|
||||
+ "6000" // push 0 where in mem to find auth param
|
||||
+ "73" // push next 20 bytes for the authority address
|
||||
+ Address.extract(keys.getPublicKey()) |
||||
.toUnprefixedHexString() // push authority address
|
||||
+ "F6" // AUTH call, should work and set authorizedBy on the frame
|
||||
+ "6000" // push 0 for return length, we don't care about the return
|
||||
+ "6000" // push 0 for return offset, we don't care about the return
|
||||
+ "6000" // push 0 for input length
|
||||
+ "6000" // push 0 for input offset
|
||||
+ "60FF" // push 255 for the value being sent
|
||||
+ "73deadbeefdeadbeefdeadbeefdeadbeefdeadbeef" // push20 the invokee address
|
||||
+ "60FF" // push 255 gas
|
||||
+ "F7"); // AUTHCALL, should work
|
||||
executor.contract(invokerAddress); |
||||
executor.execute(codeBytes, authParam, Wei.ZERO, invokerAddress); |
||||
verify(this.spyingMessageCallProcessor, times(2)) |
||||
.start(frameCaptor.capture(), any()); // one for parent frame, one for child
|
||||
List<MessageFrame> frames = frameCaptor.getAllValues(); |
||||
assertThat(frames.get(0).getStackItem(0)).isEqualTo((Bytes.of(1))); |
||||
} |
||||
|
||||
@Test |
||||
public void unauthorizedAuthCall() { |
||||
final EVM pragueEVM = |
||||
MainnetEVMs.prague(new PragueGasCalculator(), BigInteger.ONE, EvmConfiguration.DEFAULT); |
||||
final EVMExecutor executor = EVMExecutor.evm(pragueEVM); |
||||
this.spyingMessageCallProcessor = |
||||
spy(new MessageCallProcessor(pragueEVM, precompileContractRegistry)); |
||||
executor.messageCallProcessor(this.spyingMessageCallProcessor); |
||||
|
||||
executor.gas(10_000_000_000L); |
||||
|
||||
final Bytes codeBytes = |
||||
Bytes.fromHexString( |
||||
"0x" |
||||
+ "6000" // push 0 for return length
|
||||
+ "6000" // push 0 for return offset
|
||||
+ "6000" // push 0 for input length
|
||||
+ "6000" // push 0 for input offset
|
||||
+ "60FF" // push 255 for the value being sent
|
||||
+ "73deadbeefdeadbeefdeadbeefdeadbeefdeadbeef" // push20 the invokee address
|
||||
+ "60FF" // push 255 gas
|
||||
+ "F7"); // AUTHCALL without prior AUTH, should fail
|
||||
|
||||
executor.execute(codeBytes, Bytes.EMPTY, Wei.ZERO, Address.ZERO); |
||||
verify(this.spyingMessageCallProcessor).start(frameCaptor.capture(), any()); |
||||
assertThat(frameCaptor.getValue().getStackItem(0)).isEqualTo(Bytes32.ZERO); |
||||
} |
||||
} |
Loading…
Reference in new issue