mirror of https://github.com/hyperledger/besu
parent
c08ad23b3b
commit
6ec7ffed83
@ -1,154 +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.Disabled; |
|
||||||
import org.junit.jupiter.api.Test; |
|
||||||
import org.mockito.ArgumentCaptor; |
|
||||||
|
|
||||||
@Disabled("EIP-3074 is out of scope for ") |
|
||||||
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