Validate JUMPDEST by pre-compile + tweak injection of blockStore by the new interface

This commit is contained in:
Roman Mandeleil 2015-01-08 19:48:37 +02:00
parent 59833f3fd6
commit 48b27d38ec
10 changed files with 152 additions and 27 deletions

View File

@ -1,6 +1,6 @@
package org.ethereum.core;
import org.ethereum.db.BlockStoreImpl;
import org.ethereum.db.BlockStore;
import org.ethereum.facade.Blockchain;
import org.ethereum.facade.Repository;
import org.ethereum.listener.EthereumListener;
@ -9,12 +9,9 @@ import org.ethereum.net.BlockQueue;
import org.ethereum.net.server.ChannelManager;
import org.ethereum.util.AdvancedDeviceUtils;
import org.ethereum.vm.ProgramInvokeFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.FileSystemUtils;
@ -23,9 +20,7 @@ import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -79,7 +74,7 @@ public class BlockchainImpl implements Blockchain {
private Repository track;
@Autowired
private BlockStoreImpl blockStore;
private BlockStore blockStore;
private Block bestBlock;
private BigInteger totalDifficulty = BigInteger.ZERO;

View File

@ -1,6 +1,11 @@
package org.ethereum.db;
import org.ethereum.core.Block;
import org.ethereum.core.TransactionReceipt;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigInteger;
import java.util.List;
/**
* @author: Roman Mandeleil
@ -10,4 +15,38 @@ import org.ethereum.core.Block;
public interface BlockStore {
public byte[] getBlockHashByNumber(long blockNumber);
@Transactional(readOnly = true)
Block getBlockByNumber(long blockNumber);
@Transactional(readOnly = true)
Block getBlockByHash(byte[] hash);
@Transactional(readOnly = true)
@SuppressWarnings("unchecked")
List<byte[]> getListOfHashesStartFrom(byte[] hash, int qty);
@Transactional
void deleteBlocksSince(long number);
@Transactional
void saveBlock(Block block, List<TransactionReceipt> receipts);
@Transactional(readOnly = true)
BigInteger getTotalDifficultySince(long number);
@Transactional(readOnly = true)
BigInteger getTotalDifficulty();
@Transactional(readOnly = true)
Block getBestBlock();
@Transactional(readOnly = true)
@SuppressWarnings("unchecked")
List<Block> getAllBlocks();
@Transactional
void reset();
TransactionReceipt getTransactionReceiptByHash(byte[] hash);
}

View File

@ -1,8 +1,13 @@
package org.ethereum.db;
import org.ethereum.core.Block;
import org.ethereum.core.TransactionReceipt;
import org.ethereum.crypto.HashUtil;
import org.ethereum.util.ByteUtil;
import java.math.BigInteger;
import java.util.List;
/**
* @author: Roman Mandeleil
* Created on: 08/01/2015 17:33
@ -16,4 +21,59 @@ public class BlockStoreDummy implements BlockStore{
byte[] data = String.valueOf(blockNumber).getBytes();
return HashUtil.sha3(data);
}
@Override
public Block getBlockByNumber(long blockNumber) {
return null;
}
@Override
public Block getBlockByHash(byte[] hash) {
return null;
}
@Override
public List<byte[]> getListOfHashesStartFrom(byte[] hash, int qty) {
return null;
}
@Override
public void deleteBlocksSince(long number) {
}
@Override
public void saveBlock(Block block, List<TransactionReceipt> receipts) {
}
@Override
public BigInteger getTotalDifficultySince(long number) {
return null;
}
@Override
public BigInteger getTotalDifficulty() {
return null;
}
@Override
public Block getBestBlock() {
return null;
}
@Override
public List<Block> getAllBlocks() {
return null;
}
@Override
public void reset() {
}
@Override
public TransactionReceipt getTransactionReceiptByHash(byte[] hash) {
return null;
}
}

View File

@ -21,7 +21,7 @@ import java.util.List;
* @author Roman Mandeleil
* @since 12.11.2014
*/
@Repository
@Repository("blockStore")
@Transactional(propagation = Propagation.SUPPORTS)
public class BlockStoreImpl implements BlockStore{
@ -31,6 +31,9 @@ public class BlockStoreImpl implements BlockStore{
@Autowired
ApplicationContext ctx;
public BlockStoreImpl() {
}
@Override
public byte[] getBlockHashByNumber(long blockNumber) {
@ -39,6 +42,7 @@ public class BlockStoreImpl implements BlockStore{
return ByteUtil.EMPTY_BYTE_ARRAY;
}
@Override
@Transactional(readOnly = true)
public Block getBlockByNumber(long blockNumber) {
@ -52,6 +56,7 @@ public class BlockStoreImpl implements BlockStore{
return new Block(vo.rlp);
}
@Override
@Transactional(readOnly = true)
public Block getBlockByHash(byte[] hash) {
@ -65,6 +70,7 @@ public class BlockStoreImpl implements BlockStore{
return new Block(vo.rlp);
}
@Override
@Transactional(readOnly = true)
@SuppressWarnings("unchecked")
public List<byte[]> getListOfHashesStartFrom(byte[] hash, int qty) {
@ -87,6 +93,7 @@ public class BlockStoreImpl implements BlockStore{
return hashes;
}
@Override
@Transactional
public void deleteBlocksSince(long number) {
@ -97,6 +104,7 @@ public class BlockStoreImpl implements BlockStore{
}
@Override
@Transactional
public void saveBlock(Block block, List<TransactionReceipt> receipts) {
@ -115,6 +123,7 @@ public class BlockStoreImpl implements BlockStore{
sessionFactory.getCurrentSession().persist(blockVO);
}
@Override
@Transactional(readOnly = true)
public BigInteger getTotalDifficultySince(long number) {
@ -127,6 +136,7 @@ public class BlockStoreImpl implements BlockStore{
}
@Override
@Transactional(readOnly = true)
public BigInteger getTotalDifficulty() {
@ -137,6 +147,7 @@ public class BlockStoreImpl implements BlockStore{
}
@Override
@Transactional(readOnly = true)
public Block getBestBlock() {
@ -151,6 +162,7 @@ public class BlockStoreImpl implements BlockStore{
return new Block(vo.rlp);
}
@Override
@Transactional(readOnly = true)
@SuppressWarnings("unchecked")
public List<Block> getAllBlocks() {
@ -166,12 +178,14 @@ public class BlockStoreImpl implements BlockStore{
return blocks;
}
@Override
@Transactional
public void reset() {
sessionFactory.getCurrentSession().
createQuery("delete from BlockVO").executeUpdate();
}
@Override
public TransactionReceipt getTransactionReceiptByHash(byte[] hash) {
List result = sessionFactory.getCurrentSession().

View File

@ -6,6 +6,7 @@ import org.ethereum.core.Transaction;
import org.ethereum.core.TransactionReceipt;
import org.ethereum.core.Wallet;
import org.ethereum.crypto.HashUtil;
import org.ethereum.db.BlockStore;
import org.ethereum.db.BlockStoreImpl;
import org.ethereum.facade.Blockchain;
import org.ethereum.facade.Repository;
@ -63,7 +64,7 @@ public class WorldManager {
private PeerDiscovery peerDiscovery;
@Autowired
private BlockStoreImpl blockStore;
private BlockStore blockStore;
@Autowired
private ChannelManager channelManager;

View File

@ -27,11 +27,7 @@ import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Stack;
import java.util.*;
import static org.ethereum.config.SystemProperties.CONFIG;
import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY;
@ -71,6 +67,8 @@ public class Program {
byte previouslyExecutedOp = 0;
boolean stopped = false;
private Set<Integer> jumpdest = new HashSet<>();
ProgramInvoke invokeData;
public Program(byte[] ops, ProgramInvoke invokeData) {
@ -83,6 +81,7 @@ public class Program {
this.programAddress = invokeData.getOwnerAddress();
this.invokeHash = invokeData.hashCode();
this.result.setRepository(invokeData.getRepository());
precompile();
}
}
@ -856,6 +855,21 @@ public class Program {
return programTrace;
}
public void precompile(){
for (int i = 0; i < ops.length; ++i){
OpCode op = OpCode.code(ops[i]);
if (op == null) continue;
if (op.equals(OpCode.JUMPDEST)) jumpdest.add(i);
if (op.asInt() >= OpCode.PUSH1.asInt() && op.asInt() <= OpCode.PUSH32.asInt()){
i += op.asInt() - OpCode.PUSH1.asInt() + 1;
}
}
}
public static String stringify(byte[] code, int index, String result) {
if (code == null || code.length == 0)
return result;
@ -889,6 +903,10 @@ public class Program {
this.listener = listener;
}
public void vallidateJumpDest(int nextPC) {
if (!jumpdest.contains(nextPC)) throw new BadJumpDestinationException();
}
public interface ProgramListener {
public void output(String out);
}

View File

@ -30,9 +30,6 @@ public class ProgramInvokeFactoryImpl implements ProgramInvokeFactory {
@Autowired
private Blockchain blockchain;
@Autowired
private BlockStoreImpl blockStore;
// Invocation by the wire tx
@Override

View File

@ -896,8 +896,7 @@ public class VM {
case JUMP: {
DataWord pos = program.stackPop();
int nextPC = pos.intValue(); // possible overflow
if (nextPC != 0 && program.getOp(nextPC) != OpCode.JUMPDEST.val())
throw program.new BadJumpDestinationException();
program.vallidateJumpDest(nextPC);
if (logger.isInfoEnabled())
hint = "~> " + nextPC;
@ -913,8 +912,7 @@ public class VM {
if (!cond.isZero()) {
int nextPC = pos.intValue(); // possible overflow
if (nextPC != 0 && program.getOp(nextPC) != OpCode.JUMPDEST.val())
throw program.new BadJumpDestinationException();
program.vallidateJumpDest(nextPC);
if (logger.isInfoEnabled())
hint = "~> " + nextPC;

View File

@ -399,14 +399,15 @@ public class VMCustomTest {
}
}
@Test // PREVHASH OP
public void testPREVHASH_1() {
@Test // BLOCKHASH OP
public void testBLOCKHASH_1() {
VM vm = new VM();
program =
new Program(Hex.decode("40"), invoke);
String s_expected_1 = "961CB117ABA86D1E596854015A1483323F18883C2D745B0BC03E87F146D2BB1C";
new Program(Hex.decode("600140"), invoke);
String s_expected_1 = "C89EFDAA54C0F20C7ADF612882DF0950F5A951637E0307CDCB4C672F298B8BC6";
vm.step(program);
vm.step(program);
DataWord item1 = program.stackPop();

View File

@ -1,5 +1,6 @@
package test.ethereum.vm;
import jdk.nashorn.internal.ir.annotations.Ignore;
import org.ethereum.facade.Repository;
import org.ethereum.util.ByteUtil;
import org.ethereum.vm.DataWord;
@ -2732,6 +2733,7 @@ public class VMTest {
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Ignore // todo: test is not testing EXTCODESIZE
@Test // EXTCODESIZE OP
public void testEXTCODESIZE_1() {
VM vm = new VM();