Fix BLOCKHASH op new rule

The blockhash retrieved by index on one of the
recent 256 blocks. If the index is out of that
window zero pushed into the stack as a result
This commit is contained in:
Roman Mandeleil 2015-01-08 18:55:52 +02:00
parent 84b1cef682
commit 59833f3fd6
17 changed files with 312 additions and 208 deletions

View File

@ -1,6 +1,6 @@
package org.ethereum.core;
import org.ethereum.db.BlockStore;
import org.ethereum.db.BlockStoreImpl;
import org.ethereum.facade.Blockchain;
import org.ethereum.facade.Repository;
import org.ethereum.listener.EthereumListener;
@ -79,7 +79,7 @@ public class BlockchainImpl implements Blockchain {
private Repository track;
@Autowired
private BlockStore blockStore;
private BlockStoreImpl blockStore;
private Block bestBlock;
private BigInteger totalDifficulty = BigInteger.ZERO;
@ -337,7 +337,8 @@ public class BlockchainImpl implements Blockchain {
for (Transaction tx : block.getTransactionsList()) {
stateLogger.info("apply block: [{}] tx: [{}] ", block.getNumber(), i);
TransactionExecutor executor = new TransactionExecutor(tx, block.getCoinbase(), track,
TransactionExecutor executor = new TransactionExecutor(tx, block.getCoinbase(),
track, blockStore,
programInvokeFactory, block);
executor.execute();

View File

@ -1,5 +1,6 @@
package org.ethereum.core;
import org.ethereum.db.BlockStore;
import org.ethereum.facade.Repository;
import org.ethereum.vm.DataWord;
import org.ethereum.vm.GasCost;
@ -33,6 +34,8 @@ public class TransactionExecutor {
private Transaction tx;
private Repository track;
private BlockStore blockStore;
private ProgramInvokeFactory programInvokeFactory;
private byte[] coinbase;
@ -41,12 +44,13 @@ public class TransactionExecutor {
private Block currentBlock;
public TransactionExecutor(Transaction tx, byte[] coinbase, Repository track,
public TransactionExecutor(Transaction tx, byte[] coinbase, Repository track,BlockStore blockStore,
ProgramInvokeFactory programInvokeFactory, Block currentBlock) {
this.tx = tx;
this.coinbase = coinbase;
this.track = track;
this.blockStore = blockStore;
this.programInvokeFactory = programInvokeFactory;
this.currentBlock = currentBlock;
}
@ -180,7 +184,7 @@ public class TransactionExecutor {
}
ProgramInvoke programInvoke =
programInvokeFactory.createProgramInvoke(tx, currentBlock, trackTx);
programInvokeFactory.createProgramInvoke(tx, currentBlock, trackTx, blockStore);
VM vm = new VM();
Program program = new Program(code, programInvoke);

View File

@ -1,179 +1,13 @@
package org.ethereum.db;
import org.ethereum.core.Block;
import org.ethereum.core.TransactionReceipt;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
/**
* @author Roman Mandeleil
* @since 12.11.2014
* @author: Roman Mandeleil
* Created on: 08/01/2015 10:27
*/
@Repository
@Transactional(propagation = Propagation.SUPPORTS)
public class BlockStore {
@Autowired
private SessionFactory sessionFactory;
public interface BlockStore {
@Autowired
ApplicationContext ctx;
@Transactional(readOnly = true)
public Block getBlockByNumber(long blockNumber) {
List result = sessionFactory.getCurrentSession().
createQuery("from BlockVO where number = :number").
setParameter("number", blockNumber).list();
if (result.size() == 0) return null;
BlockVO vo = (BlockVO) result.get(0);
return new Block(vo.rlp);
}
@Transactional(readOnly = true)
public Block getBlockByHash(byte[] hash) {
List result = sessionFactory.getCurrentSession().
createQuery("from BlockVO where hash = :hash").
setParameter("hash", hash).list();
if (result.size() == 0) return null;
BlockVO vo = (BlockVO) result.get(0);
return new Block(vo.rlp);
}
@Transactional(readOnly = true)
@SuppressWarnings("unchecked")
public List<byte[]> getListOfHashesStartFrom(byte[] hash, int qty) {
List<byte[]> hashes = new ArrayList<>();
// find block number of that block hash
Block block = getBlockByHash(hash);
if (block == null) return hashes;
List<byte[]> result = sessionFactory.getCurrentSession().
createQuery("select hash from BlockVO where number <= :number and number >= :limit order by number desc").
setParameter("number", block.getNumber()).
setParameter("limit", block.getNumber() - qty).
setMaxResults(qty).list();
for (byte[] h : result)
hashes.add(h);
return hashes;
}
@Transactional
public void deleteBlocksSince(long number) {
sessionFactory.getCurrentSession().
createQuery("delete from BlockVO where number > :number").
setParameter("number", number).
executeUpdate();
}
@Transactional
public void saveBlock(Block block, List<TransactionReceipt> receipts) {
BlockVO blockVO = new BlockVO(block.getNumber(), block.getHash(),
block.getEncoded(), block.getCumulativeDifficulty());
for (TransactionReceipt receipt : receipts) {
byte[] hash = receipt.getTransaction().getHash();
byte[] rlp = receipt.getEncoded();
TransactionReceiptVO transactionReceiptVO = new TransactionReceiptVO(hash, rlp);
sessionFactory.getCurrentSession().persist(transactionReceiptVO);
}
sessionFactory.getCurrentSession().persist(blockVO);
}
@Transactional(readOnly = true)
public BigInteger getTotalDifficultySince(long number) {
BigInteger result = (BigInteger) sessionFactory.getCurrentSession().
createQuery("select sum(cummulativeDifficulty) from BlockVO where number > :number").
setParameter("number", number).
uniqueResult();
return result;
}
@Transactional(readOnly = true)
public BigInteger getTotalDifficulty() {
BigInteger result = (BigInteger) sessionFactory.getCurrentSession().
createQuery("select sum(cummulativeDifficulty) from BlockVO").uniqueResult();
return result;
}
@Transactional(readOnly = true)
public Block getBestBlock() {
Long bestNumber = (Long)
sessionFactory.getCurrentSession().createQuery("select max(number) from BlockVO").uniqueResult();
List result = sessionFactory.getCurrentSession().
createQuery("from BlockVO where number = :number").setParameter("number", bestNumber).list();
if (result.isEmpty()) return null;
BlockVO vo = (BlockVO) result.get(0);
return new Block(vo.rlp);
}
@Transactional(readOnly = true)
@SuppressWarnings("unchecked")
public List<Block> getAllBlocks() {
List<BlockVO> result = sessionFactory.getCurrentSession().
createQuery("from BlockVO").list();
ArrayList<Block> blocks = new ArrayList<>();
for (BlockVO blockVO : result) {
blocks.add(new Block(blockVO.getRlp()));
}
return blocks;
}
@Transactional
public void reset() {
sessionFactory.getCurrentSession().
createQuery("delete from BlockVO").executeUpdate();
}
public TransactionReceipt getTransactionReceiptByHash(byte[] hash) {
List result = sessionFactory.getCurrentSession().
createQuery("from TransactionReceiptVO where hash = :hash").
setParameter("hash", hash).list();
if (result.size() == 0) return null;
TransactionReceiptVO vo = (TransactionReceiptVO) result.get(0);
return new TransactionReceipt(vo.rlp);
}
public byte[] getBlockHashByNumber(long blockNumber);
}

View File

@ -0,0 +1,19 @@
package org.ethereum.db;
import org.ethereum.crypto.HashUtil;
import org.ethereum.util.ByteUtil;
/**
* @author: Roman Mandeleil
* Created on: 08/01/2015 17:33
*/
public class BlockStoreDummy implements BlockStore{
@Override
public byte[] getBlockHashByNumber(long blockNumber) {
byte[] data = String.valueOf(blockNumber).getBytes();
return HashUtil.sha3(data);
}
}

View File

@ -0,0 +1,187 @@
package org.ethereum.db;
import org.ethereum.core.Block;
import org.ethereum.core.TransactionReceipt;
import org.ethereum.util.ByteUtil;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
/**
* @author Roman Mandeleil
* @since 12.11.2014
*/
@Repository
@Transactional(propagation = Propagation.SUPPORTS)
public class BlockStoreImpl implements BlockStore{
@Autowired
private SessionFactory sessionFactory;
@Autowired
ApplicationContext ctx;
@Override
public byte[] getBlockHashByNumber(long blockNumber) {
Block block = getBlockByNumber(blockNumber);
if (block != null) return block.getHash();
return ByteUtil.EMPTY_BYTE_ARRAY;
}
@Transactional(readOnly = true)
public Block getBlockByNumber(long blockNumber) {
List result = sessionFactory.getCurrentSession().
createQuery("from BlockVO where number = :number").
setParameter("number", blockNumber).list();
if (result.size() == 0) return null;
BlockVO vo = (BlockVO) result.get(0);
return new Block(vo.rlp);
}
@Transactional(readOnly = true)
public Block getBlockByHash(byte[] hash) {
List result = sessionFactory.getCurrentSession().
createQuery("from BlockVO where hash = :hash").
setParameter("hash", hash).list();
if (result.size() == 0) return null;
BlockVO vo = (BlockVO) result.get(0);
return new Block(vo.rlp);
}
@Transactional(readOnly = true)
@SuppressWarnings("unchecked")
public List<byte[]> getListOfHashesStartFrom(byte[] hash, int qty) {
List<byte[]> hashes = new ArrayList<>();
// find block number of that block hash
Block block = getBlockByHash(hash);
if (block == null) return hashes;
List<byte[]> result = sessionFactory.getCurrentSession().
createQuery("select hash from BlockVO where number <= :number and number >= :limit order by number desc").
setParameter("number", block.getNumber()).
setParameter("limit", block.getNumber() - qty).
setMaxResults(qty).list();
for (byte[] h : result)
hashes.add(h);
return hashes;
}
@Transactional
public void deleteBlocksSince(long number) {
sessionFactory.getCurrentSession().
createQuery("delete from BlockVO where number > :number").
setParameter("number", number).
executeUpdate();
}
@Transactional
public void saveBlock(Block block, List<TransactionReceipt> receipts) {
BlockVO blockVO = new BlockVO(block.getNumber(), block.getHash(),
block.getEncoded(), block.getCumulativeDifficulty());
for (TransactionReceipt receipt : receipts) {
byte[] hash = receipt.getTransaction().getHash();
byte[] rlp = receipt.getEncoded();
TransactionReceiptVO transactionReceiptVO = new TransactionReceiptVO(hash, rlp);
sessionFactory.getCurrentSession().persist(transactionReceiptVO);
}
sessionFactory.getCurrentSession().persist(blockVO);
}
@Transactional(readOnly = true)
public BigInteger getTotalDifficultySince(long number) {
BigInteger result = (BigInteger) sessionFactory.getCurrentSession().
createQuery("select sum(cummulativeDifficulty) from BlockVO where number > :number").
setParameter("number", number).
uniqueResult();
return result;
}
@Transactional(readOnly = true)
public BigInteger getTotalDifficulty() {
BigInteger result = (BigInteger) sessionFactory.getCurrentSession().
createQuery("select sum(cummulativeDifficulty) from BlockVO").uniqueResult();
return result;
}
@Transactional(readOnly = true)
public Block getBestBlock() {
Long bestNumber = (Long)
sessionFactory.getCurrentSession().createQuery("select max(number) from BlockVO").uniqueResult();
List result = sessionFactory.getCurrentSession().
createQuery("from BlockVO where number = :number").setParameter("number", bestNumber).list();
if (result.isEmpty()) return null;
BlockVO vo = (BlockVO) result.get(0);
return new Block(vo.rlp);
}
@Transactional(readOnly = true)
@SuppressWarnings("unchecked")
public List<Block> getAllBlocks() {
List<BlockVO> result = sessionFactory.getCurrentSession().
createQuery("from BlockVO").list();
ArrayList<Block> blocks = new ArrayList<>();
for (BlockVO blockVO : result) {
blocks.add(new Block(blockVO.getRlp()));
}
return blocks;
}
@Transactional
public void reset() {
sessionFactory.getCurrentSession().
createQuery("delete from BlockVO").executeUpdate();
}
public TransactionReceipt getTransactionReceiptByHash(byte[] hash) {
List result = sessionFactory.getCurrentSession().
createQuery("from TransactionReceiptVO where hash = :hash").
setParameter("hash", hash).list();
if (result.size() == 0) return null;
TransactionReceiptVO vo = (TransactionReceiptVO) result.get(0);
return new TransactionReceipt(vo.rlp);
}
}

View File

@ -2,6 +2,7 @@ package org.ethereum.jsontestsuite;
import org.ethereum.core.Block;
import org.ethereum.core.Transaction;
import org.ethereum.db.BlockStore;
import org.ethereum.facade.Repository;
import org.ethereum.util.ByteUtil;
import org.ethereum.vm.DataWord;
@ -26,18 +27,19 @@ public class TestProgramInvokeFactory implements ProgramInvokeFactory {
@Override
public ProgramInvoke createProgramInvoke(Transaction tx, Block block, Repository repository) {
return generalInvoke(tx, repository);
public ProgramInvoke createProgramInvoke(Transaction tx, Block block, Repository repository, BlockStore blockStore) {
return generalInvoke(tx, repository, blockStore);
}
@Override
public ProgramInvoke createProgramInvoke(Program program, DataWord toAddress, DataWord inValue, DataWord inGas,
BigInteger balanceInt, byte[] dataIn, Repository repository) {
BigInteger balanceInt, byte[] dataIn,
Repository repository, BlockStore blockStore) {
return null;
}
private ProgramInvoke generalInvoke(Transaction tx, Repository repository) {
private ProgramInvoke generalInvoke(Transaction tx, Repository repository ,BlockStore blockStore) {
/*** ADDRESS op ***/
// YP: Get address of currently executing account.
@ -88,7 +90,7 @@ public class TestProgramInvokeFactory implements ProgramInvokeFactory {
return new ProgramInvokeImpl(address, origin, caller, balance,
gasPrice, gas, callValue, data, lastHash, coinbase,
timestamp, number, difficulty, gaslimit, repository);
timestamp, number, difficulty, gaslimit, repository, blockStore);
}
}

View File

@ -2,6 +2,7 @@ package org.ethereum.jsontestsuite;
import org.ethereum.core.BlockchainImpl;
import org.ethereum.core.TransactionExecutor;
import org.ethereum.db.BlockStoreDummy;
import org.ethereum.db.ByteArrayWrapper;
import org.ethereum.db.ContractDetails;
import org.ethereum.db.RepositoryDummy;
@ -88,8 +89,9 @@ public class TestRunner {
blockchain.startTracking();
Repository track = repository.startTracking();
TransactionExecutor executor = new TransactionExecutor(tx, coinbase, track,
invokeFactory, null);
TransactionExecutor executor =
new TransactionExecutor(tx, coinbase, track, new BlockStoreDummy(),
invokeFactory, blockchain.getBestBlock());
executor.execute();
track.commit();
@ -179,7 +181,7 @@ public class TestRunner {
ProgramInvoke programInvoke = new ProgramInvokeImpl(address, origin, caller, balance,
gasPrice, gas, callValue, msgData, lastHash, coinbase,
timestamp, number, difficulty, gaslimit, repository, true);
timestamp, number, difficulty, gaslimit, repository, null, true);
/* 3. Create Program - exec.code */
/* 4. run VM */

View File

@ -6,7 +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;
import org.ethereum.listener.EthereumListener;
@ -63,7 +63,7 @@ public class WorldManager {
private PeerDiscovery peerDiscovery;
@Autowired
private BlockStore blockStore;
private BlockStoreImpl blockStore;
@Autowired
private ChannelManager channelManager;

View File

@ -190,7 +190,7 @@ public enum OpCode {
* (0x40) Get hash of most recent
* complete block
*/
PREVHASH(0x40, 0),
BLOCKHASH(0x40, 1),
/**
* (0x41) Get the blocks coinbase address
*/

View File

@ -1,6 +1,7 @@
package org.ethereum.vm;
import org.ethereum.crypto.HashUtil;
import org.ethereum.db.BlockStore;
import org.ethereum.db.ContractDetails;
import org.ethereum.facade.Repository;
import org.ethereum.util.ByteUtil;
@ -350,7 +351,7 @@ public class Program {
// [5] COOK THE INVOKE AND EXECUTE
ProgramInvoke programInvoke = programInvokeFactory.createProgramInvoke(
this, new DataWord(newAddress), DataWord.ZERO, gasLimit,
newBalance, null, track);
newBalance, null, track, this.invokeData.getBlockStore());
ProgramResult result = null;
@ -466,7 +467,7 @@ public class Program {
Repository trackRepository = result.getRepository().startTracking();
ProgramInvoke programInvoke = programInvokeFactory.createProgramInvoke(
this, new DataWord(contextAddress), msg.getEndowment(),
msg.getGas(), contextBalance, data, trackRepository);
msg.getGas(), contextBalance, data, trackRepository, this.invokeData.getBlockStore());
ProgramResult result = null;
@ -574,6 +575,22 @@ public class Program {
return this.programAddress.clone();
}
public DataWord getBlockHash(int index) {
// todo:
/// Hash of a block if within the last 256 blocks, or h256() otherwise.
// h256 blockhash(u256 _number) {return
// _number < currentBlock.number && _number >= (std::max<u256>(256, currentBlock.number) - 256) ?
// lastHashes[(unsigned)(currentBlock.number - 1 - _number)] :
// h256(); }
return index < this.getNumber().longValue() && index >= Math.max(256, this.getNumber().intValue()) - 256?
new DataWord(this.invokeData.getBlockStore().getBlockHashByNumber(index)):
DataWord.ZERO;
}
public DataWord getBalance(DataWord address) {
if (invokeData == null) return DataWord.ZERO_EMPTY_ARRAY;

View File

@ -1,5 +1,6 @@
package org.ethereum.vm;
import org.ethereum.db.BlockStore;
import org.ethereum.facade.Repository;
/**
@ -41,12 +42,15 @@ public interface ProgramInvoke {
public DataWord getDifficulty();
public DataWord getGaslimit();
public Repository getRepository();
public boolean byTransaction();
boolean byTestingSuite();
public int getCallDeep();
public Repository getRepository();
public BlockStore getBlockStore();
}

View File

@ -2,6 +2,7 @@ package org.ethereum.vm;
import org.ethereum.core.Block;
import org.ethereum.core.Transaction;
import org.ethereum.db.BlockStore;
import org.ethereum.facade.Repository;
import java.math.BigInteger;
@ -12,12 +13,13 @@ import java.math.BigInteger;
*/
public interface ProgramInvokeFactory {
public ProgramInvoke createProgramInvoke(Transaction tx, Block block, Repository repository);
public ProgramInvoke createProgramInvoke(Transaction tx, Block block,
Repository repository, BlockStore blockStore);
public ProgramInvoke createProgramInvoke(Program program, DataWord toAddress,
DataWord inValue, DataWord inGas,
BigInteger balanceInt, byte[] dataIn,
Repository repository);
Repository repository, BlockStore blockStore);
}

View File

@ -2,6 +2,8 @@ package org.ethereum.vm;
import org.ethereum.core.Block;
import org.ethereum.core.Transaction;
import org.ethereum.db.BlockStore;
import org.ethereum.db.BlockStoreImpl;
import org.ethereum.facade.Blockchain;
import org.ethereum.facade.Repository;
import org.ethereum.util.ByteUtil;
@ -27,11 +29,15 @@ public class ProgramInvokeFactoryImpl implements ProgramInvokeFactory {
@Autowired
private Blockchain blockchain;
@Autowired
private BlockStoreImpl blockStore;
// Invocation by the wire tx
@Override
public ProgramInvoke createProgramInvoke(Transaction tx, Block block, Repository repository) {
public ProgramInvoke createProgramInvoke(Transaction tx, Block block, Repository repository,
BlockStore blockStore) {
// https://ethereum.etherpad.mozilla.org/26
Block lastBlock = blockchain.getBestBlock();
@ -119,7 +125,7 @@ public class ProgramInvokeFactoryImpl implements ProgramInvokeFactory {
ProgramInvoke programInvoke =
new ProgramInvokeImpl(address, origin, caller, balance, gasPrice, gas, callValue, data,
lastHash, coinbase, timestamp, number, difficulty, gaslimit,
repository);
repository, blockStore);
return programInvoke;
}
@ -131,7 +137,7 @@ public class ProgramInvokeFactoryImpl implements ProgramInvokeFactory {
public ProgramInvoke createProgramInvoke(Program program, DataWord toAddress,
DataWord inValue, DataWord inGas,
BigInteger balanceInt, byte[] dataIn,
Repository repository) {
Repository repository, BlockStore blockStore) {
DataWord address = toAddress;
DataWord origin = program.getOriginAddress();
@ -184,6 +190,6 @@ public class ProgramInvokeFactoryImpl implements ProgramInvokeFactory {
return new ProgramInvokeImpl(address, origin, caller, balance, gasPrice, gas, callValue,
data, lastHash, coinbase, timestamp, number, difficulty, gasLimit,
repository, program.invokeData.getCallDeep() + 1);
repository, program.invokeData.getCallDeep() + 1, blockStore);
}
}

View File

@ -1,5 +1,6 @@
package org.ethereum.vm;
import org.ethereum.db.BlockStore;
import org.ethereum.facade.Repository;
import java.math.BigInteger;
@ -13,6 +14,7 @@ import java.util.Map;
*/
public class ProgramInvokeImpl implements ProgramInvoke {
private BlockStore blockStore;
/**
* TRANSACTION env **
*/
@ -39,7 +41,7 @@ public class ProgramInvokeImpl implements ProgramInvoke {
DataWord gasPrice, DataWord gas, DataWord callValue, byte[] msgData,
DataWord lastHash, DataWord coinbase, DataWord timestamp, DataWord number, DataWord
difficulty,
DataWord gaslimit, Repository repository, int callDeep) {
DataWord gaslimit, Repository repository, int callDeep, BlockStore blockStore) {
// Transaction env
this.address = address;
@ -62,15 +64,16 @@ public class ProgramInvokeImpl implements ProgramInvoke {
this.repository = repository;
this.byTransaction = false;
this.callDeep = callDeep;
this.blockStore = blockStore;
}
public ProgramInvokeImpl(byte[] address, byte[] origin, byte[] caller, byte[] balance,
byte[] gasPrice, byte[] gas, byte[] callValue, byte[] msgData,
byte[] lastHash, byte[] coinbase, long timestamp, long number, byte[] difficulty,
long gaslimit,
Repository repository, boolean byTestingSuite) {
Repository repository, BlockStore blockStore,boolean byTestingSuite) {
this(address, origin, caller, balance, gasPrice, gas, callValue, msgData, lastHash, coinbase,
timestamp, number, difficulty, gaslimit, repository);
timestamp, number, difficulty, gaslimit, repository, blockStore);
this.byTestingSuite = byTestingSuite;
}
@ -79,7 +82,7 @@ public class ProgramInvokeImpl implements ProgramInvoke {
byte[] gasPrice, byte[] gas, byte[] callValue, byte[] msgData,
byte[] lastHash, byte[] coinbase, long timestamp, long number, byte[] difficulty,
long gaslimit,
Repository repository) {
Repository repository, BlockStore blockStore) {
// Transaction env
this.address = new DataWord(address);
@ -100,6 +103,7 @@ public class ProgramInvokeImpl implements ProgramInvoke {
this.gaslimit = new DataWord(gaslimit);
this.repository = repository;
this.blockStore = blockStore;
}
/* ADDRESS op */
@ -239,6 +243,11 @@ public class ProgramInvokeImpl implements ProgramInvoke {
return repository;
}
@Override
public BlockStore getBlockStore() {
return blockStore;
}
@Override
public boolean byTransaction() {
return byTransaction;

View File

@ -2,6 +2,8 @@ package org.ethereum.vm;
import org.ethereum.crypto.ECKey;
import org.ethereum.crypto.HashUtil;
import org.ethereum.db.BlockStore;
import org.ethereum.db.BlockStoreDummy;
import org.ethereum.db.RepositoryImpl;
import org.ethereum.facade.Repository;
@ -214,6 +216,11 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
return this.repository;
}
@Override
public BlockStore getBlockStore() {
return new BlockStoreDummy();
}
public void setRepository(Repository repository) {
this.repository = repository;
}

View File

@ -716,13 +716,16 @@ public class VM {
/**
* Block Information
*/
case PREVHASH: {
DataWord prevHash = program.getPrevHash();
case BLOCKHASH: {
int blockIndex = program.stackPop().intValue();
DataWord blockHash = program.getBlockHash(blockIndex);
if (logger.isInfoEnabled())
hint = "prevHash: " + prevHash;
hint = "blockHash: " + blockHash;
program.stackPush(prevHash);
program.stackPush(blockHash);
program.step();
}
break;

View File

@ -18,9 +18,8 @@ public class GitHubStateTest {
@Ignore
@Test
public void stSingleTest() throws ParseException {
String json = JSONReader.loadJSON("StateTests/stSystemOperationsTest.json");
GitHubJSONTestSuite.runGitHubJsonStateTest(json, "createNameRegistrator");
GitHubJSONTestSuite.runGitHubJsonStateTest(json, "CallToReturn1ForDynamicJump1");
}
@Ignore
@ -28,7 +27,7 @@ public class GitHubStateTest {
public void runWithExcludedTest() throws ParseException {
Set<String> excluded = new HashSet<>();
excluded.add("createNameRegistratorValueTooHigh");
excluded.add("CallToReturn1ForDynamicJump1");
String json = JSONReader.loadJSON("StateTests/stSystemOperationsTest.json");
GitHubJSONTestSuite.runGitHubJsonStateTest(json, excluded);
@ -89,6 +88,14 @@ public class GitHubStateTest {
}
@Test
public void stBlockHashTest() throws ParseException {
String json = JSONReader.loadJSON("StateTests/stBlockHashTest.json");
GitHubJSONTestSuite.runGitHubJsonStateTest(json);
}
@Test
public void stSystemOperationsTest() throws ParseException {