From 179888a7d3cf27e99c8ce80e2732bd3ace586cf7 Mon Sep 17 00:00:00 2001 From: Dmitry Shmatko Date: Tue, 10 Apr 2018 16:58:22 +0300 Subject: [PATCH] Temporary EIP-86 partial implementation --- .../config/net/CasperTestNetConfig.java | 22 +++++++++++++++++++ .../ethereum/casper/core/CasperFacade.java | 6 +++++ .../core/CasperTransactionExecutor.java | 11 +--------- .../config/blockchain/HomesteadConfig.java | 3 +-- .../java/org/ethereum/core/Transaction.java | 11 ++++++---- 5 files changed, 37 insertions(+), 16 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java b/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java index e9be295c4b..f3060e6554 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/config/net/CasperTestNetConfig.java @@ -17,6 +17,7 @@ */ package org.ethereum.casper.config.net; +import org.ethereum.casper.core.CasperFacade; import org.ethereum.config.BlockchainConfig; import org.ethereum.config.Constants; import org.ethereum.config.ConstantsAdapter; @@ -24,11 +25,15 @@ import org.ethereum.config.blockchain.Eip150HFConfig; import org.ethereum.config.blockchain.FrontierConfig; import org.ethereum.config.net.BaseNetConfig; +import org.ethereum.core.Transaction; import org.ethereum.crypto.ECKey; import org.ethereum.vm.GasCost; import org.spongycastle.util.encoders.Hex; import java.math.BigInteger; +import java.util.Objects; + +import static org.ethereum.config.blockchain.HomesteadConfig.SECP256K1N_HALF; public class CasperTestNetConfig extends BaseNetConfig { @@ -38,6 +43,7 @@ public class CasperTestNetConfig extends BaseNetConfig { public static final double BASE_INTEREST_FACTOR = 0.1; public static final double BASE_PENALTY_FACTOR = 0.0001; public static final int MIN_DEPOSIT_ETH = 1500; + private byte[] casperAddress = null; public final static ECKey NULL_SIGN_SENDER = ECKey.fromPrivate(Hex.decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); @@ -85,9 +91,25 @@ public boolean eip161() { public Constants getConstants() { return constants; } + + @Override + public boolean acceptTransactionSignature(Transaction tx) { + if (tx.getSignature() != null) { + // Homestead-like check + if (!tx.getSignature().validateComponents() || + tx.getSignature().s.compareTo(SECP256K1N_HALF) > 0) return false; + } else { + if (casperAddress == null || !CasperFacade.isVote(tx, casperAddress)) return false; + } + return tx.getChainId() == null || Objects.equals(getChainId(), tx.getChainId()); + } } public CasperTestNetConfig() { add(0, new CasperConfig(new FrontierConfig())); } + + public void setCasperAddress(byte[] casperAddress) { + this.casperAddress = casperAddress; + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java index a2549d721f..d28011e583 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperFacade.java @@ -20,6 +20,8 @@ import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.tuple.Pair; import org.ethereum.casper.config.CasperProperties; +import org.ethereum.casper.config.net.CasperTestNetConfig; +import org.ethereum.config.BlockchainNetConfig; import org.ethereum.config.SystemProperties; import org.ethereum.core.Block; import org.ethereum.core.CallTransaction; @@ -81,6 +83,10 @@ private void init() { byte[] casperAddress = res.getKey(); this.initTxs = res.getValue(); systemProperties.setCasperAddress(casperAddress); + BlockchainNetConfig netConfig = systemProperties.getBlockchainConfig(); + if (netConfig instanceof CasperTestNetConfig) { + ((CasperTestNetConfig) netConfig).setCasperAddress(casperAddress); + } this.contractAddress = Hex.toHexString(casperAddress); logger.info("Casper contract address set to [0x{}]", contractAddress); String casperAbi = systemProperties.getCasperAbi(); diff --git a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java index 6276f58083..ab73b17235 100644 --- a/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java +++ b/ethereumj-core/src/main/java/org/ethereum/casper/core/CasperTransactionExecutor.java @@ -74,17 +74,12 @@ public void init() { } } - @Override - protected boolean isSignatureValid() { - return isCasperVote() || super.isSignatureValid(); - } - @Override public void execute() { if (!readyToExecute) return; - if (!localCall && !isCasperVote()) { + if (!localCall && !isCasperServiceTx()) { track.increaseNonce(tx.getSender()); BigInteger txGasLimit = toBI(tx.getGasLimit()); @@ -106,10 +101,6 @@ private boolean isCasperServiceTx() { return CasperFacade.isServiceTx(tx, ((CasperProperties) config).getCasperAddress()); } - private boolean isCasperVote() { - return CasperFacade.isVote(tx, ((CasperProperties) config).getCasperAddress()); - } - @Override protected void payRewards(final TransactionExecutionSummary summary) { if (isCasperServiceTx()) { diff --git a/ethereumj-core/src/main/java/org/ethereum/config/blockchain/HomesteadConfig.java b/ethereumj-core/src/main/java/org/ethereum/config/blockchain/HomesteadConfig.java index 745d7e212a..270fd7f670 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/blockchain/HomesteadConfig.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/blockchain/HomesteadConfig.java @@ -29,7 +29,7 @@ */ public class HomesteadConfig extends FrontierConfig { - static final BigInteger SECP256K1N_HALF = Constants.getSECP256K1N().divide(BigInteger.valueOf(2)); + public static final BigInteger SECP256K1N_HALF = Constants.getSECP256K1N().divide(BigInteger.valueOf(2)); public static class HomesteadConstants extends FrontierConstants { @Override @@ -68,7 +68,6 @@ public long getTransactionCost(Transaction tx) { @Override public boolean acceptTransactionSignature(Transaction tx) { if (!super.acceptTransactionSignature(tx)) return false; - if (tx.getSignature() == null) return false; return tx.getSignature().s.compareTo(SECP256K1N_HALF) <= 0; } } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/Transaction.java b/ethereumj-core/src/main/java/org/ethereum/core/Transaction.java index a1254e4025..59e84f11b1 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Transaction.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Transaction.java @@ -160,7 +160,8 @@ public Transaction(byte[] nonce, byte[] gasPrice, byte[] gasLimit, byte[] receiv } - private Integer extractChainIdFromV(BigInteger bv) { + private Integer extractChainIdFromRawSignature(BigInteger bv, byte[] r, byte[] s) { + if (r == null && s == null) return bv.intValue(); // EIP 86 if (bv.bitLength() > 31) return Integer.MAX_VALUE; // chainId is limited to 31 bits, longer are not valid for now long v = bv.longValue(); if (v == LOWER_REAL_V || v == (LOWER_REAL_V + 1)) return null; @@ -213,10 +214,12 @@ public synchronized void rlpParse() { if (transaction.get(6).getRLPData() != null) { byte[] vData = transaction.get(6).getRLPData(); BigInteger v = ByteUtil.bytesToBigInteger(vData); - this.chainId = extractChainIdFromV(v); byte[] r = transaction.get(7).getRLPData(); byte[] s = transaction.get(8).getRLPData(); - this.signature = ECDSASignature.fromComponents(r, s, getRealV(v)); + this.chainId = extractChainIdFromRawSignature(v, r, s); + if (r != null && s != null) { + this.signature = ECDSASignature.fromComponents(r, s, getRealV(v)); + } } else { logger.debug("RLP encoded tx is not signed!"); } @@ -381,7 +384,7 @@ public synchronized byte[] getSender() { if (sendAddress == null && getSignature() != null) { sendAddress = ECKey.signatureToAddress(getRawHash(), getSignature()); } - // FIXME: Casper votes, we shouldn't do it this for Transaction itself + // TODO: check for side-effects return sendAddress == null ? NULL_SENDER : sendAddress; } catch (SignatureException e) { logger.error(e.getMessage(), e);