Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ private static byte[] encodeRes(byte[] w1, byte[] w2) {
return res;
}

public static class Identity extends PrecompiledContract {
public static class Identity implements PrecompiledContract {

public Identity() {
}
Expand All @@ -114,12 +114,12 @@ public long getGasForData(byte[] data) {
}

@Override
public Pair<Boolean, byte[]> execute(byte[] data, PrecompiledContractContext context) {
return Pair.of(true, data);
public Pair<Boolean, byte[]> execute(PrecompiledContractContext invoke) {
return Pair.of(true, invoke.getData());
}
}

public static class Sha256 extends PrecompiledContract {
public static class Sha256 implements PrecompiledContract {
@Override
public long getGasForData(byte[] data) {
// gas charge for the execution:
Expand All @@ -132,12 +132,13 @@ public long getGasForData(byte[] data) {
}

@Override
public Pair<Boolean, byte[]> execute(byte[] data, PrecompiledContractContext context) {
public Pair<Boolean, byte[]> execute(PrecompiledContractContext invoke) {
byte[] data = invoke.getData();
return Pair.of(true, HashUtil.sha256(data == null ? EMPTY_BYTE_ARRAY : data));
}
}

public static class Ripempd160 extends PrecompiledContract {
public static class Ripempd160 implements PrecompiledContract {
@Override
public long getGasForData(byte[] data) {
// gas charge for the execution:
Expand All @@ -150,7 +151,8 @@ public long getGasForData(byte[] data) {
}

@Override
public Pair<Boolean, byte[]> execute(byte[] data, PrecompiledContractContext context) {
public Pair<Boolean, byte[]> execute(PrecompiledContractContext invoke) {
byte[] data = invoke.getData();
byte[] result;
if (data == null) {
result = HashUtil.ripemd160(EMPTY_BYTE_ARRAY);
Expand All @@ -162,15 +164,17 @@ public Pair<Boolean, byte[]> execute(byte[] data, PrecompiledContractContext con
}
}

public static class ECRecover extends PrecompiledContract {
public static class ECRecover implements PrecompiledContract {

@Override
public long getGasForData(byte[] data) {
return 3000;
}

@Override
public Pair<Boolean, byte[]> execute(byte[] data, PrecompiledContractContext context) {
public Pair<Boolean, byte[]> execute(PrecompiledContractContext invoke) {
byte[] data = invoke.getData();

byte[] h = new byte[32];
byte[] v = new byte[32];
byte[] r = new byte[32];
Expand Down Expand Up @@ -216,7 +220,7 @@ private static boolean validateV(byte[] v) {
*
* Returns an output as a byte array with the same length as the modulus
*/
public static class ModExp extends PrecompiledContract {
public static class ModExp implements PrecompiledContract {

private static final BigInteger GQUAD_DIVISOR = BigInteger.valueOf(20);

Expand Down Expand Up @@ -246,7 +250,8 @@ public long getGasForData(byte[] data) {
}

@Override
public Pair<Boolean, byte[]> execute(byte[] data, PrecompiledContractContext context) {
public Pair<Boolean, byte[]> execute(PrecompiledContractContext invoke) {
byte[] data = invoke.getData();
if (data == null) {
return Pair.of(true, EMPTY_BYTE_ARRAY);
}
Expand Down Expand Up @@ -331,15 +336,16 @@ private BigInteger parseArg(byte[] data, int offset, int len) {
* resulting point (x', y'), where x and y encoded as 32-byte left-padded
* integers<br/>
*/
public static class BN128Addition extends PrecompiledContract {
public static class BN128Addition implements PrecompiledContract {

@Override
public long getGasForData(byte[] data) {
return 500;
}

@Override
public Pair<Boolean, byte[]> execute(byte[] data, PrecompiledContractContext context) {
public Pair<Boolean, byte[]> execute(PrecompiledContractContext invoke) {
byte[] data = invoke.getData();
if (data == null) {
data = EMPTY_BYTE_ARRAY;
}
Expand Down Expand Up @@ -380,15 +386,16 @@ public Pair<Boolean, byte[]> execute(byte[] data, PrecompiledContractContext con
* resulting point (x', y'), where x and y encoded as 32-byte left-padded
* integers<br/>
*/
public static class BN128Multiplication extends PrecompiledContract {
public static class BN128Multiplication implements PrecompiledContract {

@Override
public long getGasForData(byte[] data) {
return 40000;
}

@Override
public Pair<Boolean, byte[]> execute(byte[] data, PrecompiledContractContext context) {
public Pair<Boolean, byte[]> execute(PrecompiledContractContext invoke) {
byte[] data = invoke.getData();
if (data == null) {
data = EMPTY_BYTE_ARRAY;
}
Expand Down Expand Up @@ -431,7 +438,7 @@ public Pair<Boolean, byte[]> execute(byte[] data, PrecompiledContractContext con
* pairing product which is either 0 or 1, encoded as 32-byte left-padded
* integer <br/>
*/
public static class BN128Pairing extends PrecompiledContract {
public static class BN128Pairing implements PrecompiledContract {

private static final int PAIR_SIZE = 192;

Expand All @@ -445,7 +452,8 @@ public long getGasForData(byte[] data) {
}

@Override
public Pair<Boolean, byte[]> execute(byte[] data, PrecompiledContractContext context) {
public Pair<Boolean, byte[]> execute(PrecompiledContractContext invoke) {
byte[] data = invoke.getData();
if (data == null) {
data = EMPTY_BYTE_ARRAY;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@

import org.ethereum.vm.util.Pair;

public abstract class PrecompiledContract {
public abstract long getGasForData(byte[] data);
public interface PrecompiledContract {

public abstract Pair<Boolean, byte[]> execute(byte[] data, PrecompiledContractContext context);
long getGasForData(byte[] data);

Pair<Boolean, byte[]> execute(PrecompiledContractContext invoke);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,39 @@
*/
package org.ethereum.vm.chainspec;

/**
* Class to manage alternate behavior provided by precompiled contracts.
*/
import java.math.BigInteger;

import org.ethereum.vm.client.Repository;

public interface PrecompiledContractContext {
}

/**
* Returns the repository track.
*
* @return the current repository track.
*/
Repository getTrack();

/**
* Returns the caller's address.
*
* @return an address
*/
byte[] getCaller();

/**
* Returns the value being transferred to this contract.
*
* NOTE: the transfer has been conducted.
*
* @return a value in {@link org.ethereum.vm.client.Unit#WEI}.
*/
BigInteger getValue();

/**
* Returns the data passed to this contract.
*
* @return a byte array
*/
byte[] getData();
}
8 changes: 0 additions & 8 deletions src/main/java/org/ethereum/vm/client/Repository.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,9 @@
import java.math.BigInteger;

import org.ethereum.vm.DataWord;
import org.ethereum.vm.chainspec.PrecompiledContractContext;

public interface Repository {

/**
* Returns the context for precompiled contract.
*
* @return
*/
PrecompiledContractContext getContext();

/**
* Checks whether an account exists.
*
Expand Down
23 changes: 22 additions & 1 deletion src/main/java/org/ethereum/vm/client/TransactionExecutor.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.ethereum.vm.DataWord;
import org.ethereum.vm.VM;
import org.ethereum.vm.chainspec.PrecompiledContract;
import org.ethereum.vm.chainspec.PrecompiledContractContext;
import org.ethereum.vm.chainspec.Spec;
import org.ethereum.vm.program.Program;
import org.ethereum.vm.program.ProgramResult;
Expand Down Expand Up @@ -175,7 +176,27 @@ protected void call() {
gasLeft = BigInteger.ZERO;
} else {
gasLeft = gasLeft.subtract(spendingGas);
Pair<Boolean, byte[]> out = precompiledContract.execute(tx.getData(), track.getContext());
Pair<Boolean, byte[]> out = precompiledContract.execute(new PrecompiledContractContext() {
@Override
public Repository getTrack() {
return track;
}

@Override
public byte[] getCaller() {
return tx.getFrom();
}

@Override
public BigInteger getValue() {
return endowment;
}

@Override
public byte[] getData() {
return tx.getData();
}
});

if (!out.getLeft()) {
logger.warn("Error executing precompiled contract 0x{}", toHexString(targetAddress));
Expand Down
23 changes: 22 additions & 1 deletion src/main/java/org/ethereum/vm/program/Program.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.ethereum.vm.OpCode;
import org.ethereum.vm.VM;
import org.ethereum.vm.chainspec.PrecompiledContract;
import org.ethereum.vm.chainspec.PrecompiledContractContext;
import org.ethereum.vm.chainspec.Spec;
import org.ethereum.vm.client.Repository;
import org.ethereum.vm.client.Transaction;
Expand Down Expand Up @@ -637,7 +638,27 @@ public void callToPrecompiledAddress(MessageCall msg, PrecompiledContract contra
this.stackPushZero();
track.rollback();
} else {
Pair<Boolean, byte[]> out = contract.execute(data, repository.getContext());
Pair<Boolean, byte[]> out = contract.execute(new PrecompiledContractContext() {
@Override
public Repository getTrack() {
return track;
}

@Override
public byte[] getCaller() {
return senderAddress;
}

@Override
public BigInteger getValue() {
return endowment;
}

@Override
public byte[] getData() {
return data;
}
});

if (out.getLeft()) {
this.refundGas(msg.getGas() - requiredGas, "refund gas from pre-compiled call");
Expand Down
Loading