Fix memory allocation and add unit tests
This commit is contained in:
parent
c51e56831a
commit
561d1dd296
|
@ -1,6 +1,7 @@
|
||||||
package org.ethereum.core;
|
package org.ethereum.core;
|
||||||
|
|
||||||
import org.ethereum.db.Repository;
|
import org.ethereum.db.RepositoryImpl;
|
||||||
|
import org.ethereum.facade.Blockchain;
|
||||||
import org.ethereum.listener.EthereumListener;
|
import org.ethereum.listener.EthereumListener;
|
||||||
import org.ethereum.manager.WorldManager;
|
import org.ethereum.manager.WorldManager;
|
||||||
import org.ethereum.net.BlockQueue;
|
import org.ethereum.net.BlockQueue;
|
||||||
|
@ -50,7 +51,7 @@ import static org.ethereum.core.Denomination.SZABO;
|
||||||
* Created on: 20/05/2014 10:44
|
* Created on: 20/05/2014 10:44
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class Blockchain implements org.ethereum.facade.Blockchain{
|
public class BlockchainImpl implements Blockchain {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger("blockchain");
|
private static final Logger logger = LoggerFactory.getLogger("blockchain");
|
||||||
private static final Logger stateLogger = LoggerFactory.getLogger("state");
|
private static final Logger stateLogger = LoggerFactory.getLogger("state");
|
||||||
|
@ -58,7 +59,7 @@ public class Blockchain implements org.ethereum.facade.Blockchain{
|
||||||
// to avoid using minGasPrice=0 from Genesis for the wallet
|
// to avoid using minGasPrice=0 from Genesis for the wallet
|
||||||
private static final long INITIAL_MIN_GAS_PRICE = 10 * SZABO.longValue();
|
private static final long INITIAL_MIN_GAS_PRICE = 10 * SZABO.longValue();
|
||||||
|
|
||||||
private Repository repository;
|
private RepositoryImpl repository;
|
||||||
private Block lastBlock;
|
private Block lastBlock;
|
||||||
|
|
||||||
// keep the index of the chain for
|
// keep the index of the chain for
|
||||||
|
@ -67,7 +68,7 @@ public class Blockchain implements org.ethereum.facade.Blockchain{
|
||||||
|
|
||||||
private final BlockQueue blockQueue = new BlockQueue();
|
private final BlockQueue blockQueue = new BlockQueue();
|
||||||
|
|
||||||
public Blockchain(Repository repository) {
|
public BlockchainImpl(RepositoryImpl repository) {
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,7 +325,7 @@ public class Blockchain implements org.ethereum.facade.Blockchain{
|
||||||
if (isContractCreation || code != null) {
|
if (isContractCreation || code != null) {
|
||||||
|
|
||||||
// START TRACKING FOR REVERT CHANGES OPTION
|
// START TRACKING FOR REVERT CHANGES OPTION
|
||||||
Repository trackRepository = repository.getTrack();
|
RepositoryImpl trackRepository = repository.getTrack();
|
||||||
trackRepository.startTracking();
|
trackRepository.startTracking();
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -385,7 +386,7 @@ public class Blockchain implements org.ethereum.facade.Blockchain{
|
||||||
* @param contractAddress
|
* @param contractAddress
|
||||||
*/
|
*/
|
||||||
private void applyProgramResult(ProgramResult result, BigInteger gasDebit,
|
private void applyProgramResult(ProgramResult result, BigInteger gasDebit,
|
||||||
Repository repository, byte[] senderAddress,
|
RepositoryImpl repository, byte[] senderAddress,
|
||||||
byte[] contractAddress, byte[] coinbase, boolean initResults) {
|
byte[] contractAddress, byte[] coinbase, boolean initResults) {
|
||||||
|
|
||||||
if (result.getException() != null
|
if (result.getException() != null
|
|
@ -3,9 +3,10 @@ package org.ethereum.db;
|
||||||
import org.codehaus.plexus.util.FileUtils;
|
import org.codehaus.plexus.util.FileUtils;
|
||||||
import org.ethereum.core.AccountState;
|
import org.ethereum.core.AccountState;
|
||||||
import org.ethereum.core.Block;
|
import org.ethereum.core.Block;
|
||||||
import org.ethereum.core.Blockchain;
|
import org.ethereum.core.BlockchainImpl;
|
||||||
import org.ethereum.core.Genesis;
|
import org.ethereum.core.Genesis;
|
||||||
import org.ethereum.crypto.HashUtil;
|
import org.ethereum.crypto.HashUtil;
|
||||||
|
import org.ethereum.facade.Repository;
|
||||||
import org.ethereum.json.EtherObjectMapper;
|
import org.ethereum.json.EtherObjectMapper;
|
||||||
import org.ethereum.json.JSONHelper;
|
import org.ethereum.json.JSONHelper;
|
||||||
import org.ethereum.listener.EthereumListener;
|
import org.ethereum.listener.EthereumListener;
|
||||||
|
@ -18,6 +19,7 @@ import org.iq80.leveldb.DBIterator;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
|
||||||
|
@ -51,7 +53,7 @@ import static org.ethereum.config.SystemProperties.CONFIG;
|
||||||
* @author: Roman Mandeleil
|
* @author: Roman Mandeleil
|
||||||
* Created on: 23/06/2014 23:01
|
* Created on: 23/06/2014 23:01
|
||||||
*/
|
*/
|
||||||
public class Repository implements org.ethereum.facade.Repository{
|
public class RepositoryImpl implements Repository {
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger("repository");
|
private Logger logger = LoggerFactory.getLogger("repository");
|
||||||
|
|
||||||
|
@ -72,7 +74,7 @@ public class Repository implements org.ethereum.facade.Repository{
|
||||||
*
|
*
|
||||||
* @See loadBlockchain() to update the stateRoot
|
* @See loadBlockchain() to update the stateRoot
|
||||||
*/
|
*/
|
||||||
public Repository() {
|
public RepositoryImpl() {
|
||||||
chainDB = new DatabaseImpl("blockchain");
|
chainDB = new DatabaseImpl("blockchain");
|
||||||
detailsDB = new DatabaseImpl("details");
|
detailsDB = new DatabaseImpl("details");
|
||||||
contractDetailsDB = new TrackDatabase(detailsDB);
|
contractDetailsDB = new TrackDatabase(detailsDB);
|
||||||
|
@ -81,15 +83,15 @@ public class Repository implements org.ethereum.facade.Repository{
|
||||||
accountStateDB = new TrackTrie(worldState);
|
accountStateDB = new TrackTrie(worldState);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Repository(TrackTrie accountStateDB, TrackDatabase contractDetailsDB) {
|
private RepositoryImpl(TrackTrie accountStateDB, TrackDatabase contractDetailsDB) {
|
||||||
this.accountStateDB = accountStateDB;
|
this.accountStateDB = accountStateDB;
|
||||||
this.contractDetailsDB = contractDetailsDB;
|
this.contractDetailsDB = contractDetailsDB;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Repository getTrack() {
|
public RepositoryImpl getTrack() {
|
||||||
TrackTrie trackState = new TrackTrie(accountStateDB);
|
TrackTrie trackState = new TrackTrie(accountStateDB);
|
||||||
TrackDatabase trackDetails = new TrackDatabase(contractDetailsDB);
|
TrackDatabase trackDetails = new TrackDatabase(contractDetailsDB);
|
||||||
return new Repository (trackState, trackDetails);
|
return new RepositoryImpl (trackState, trackDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startTracking() {
|
public void startTracking() {
|
||||||
|
@ -121,8 +123,8 @@ public class Repository implements org.ethereum.facade.Repository{
|
||||||
this.worldState.sync();
|
this.worldState.sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Blockchain loadBlockchain() {
|
public BlockchainImpl loadBlockchain() {
|
||||||
Blockchain blockchain = WorldManager.getInstance().getBlockchain();
|
BlockchainImpl blockchain = WorldManager.getInstance().getBlockchain();
|
||||||
DBIterator iterator = chainDB.iterator();
|
DBIterator iterator = chainDB.iterator();
|
||||||
try {
|
try {
|
||||||
if (!iterator.hasNext()) {
|
if (!iterator.hasNext()) {
|
|
@ -7,7 +7,7 @@ import java.util.concurrent.Future;
|
||||||
|
|
||||||
import org.ethereum.core.Transaction;
|
import org.ethereum.core.Transaction;
|
||||||
import org.ethereum.core.Wallet;
|
import org.ethereum.core.Wallet;
|
||||||
import org.ethereum.db.Repository;
|
import org.ethereum.db.RepositoryImpl;
|
||||||
import org.ethereum.listener.EthereumListener;
|
import org.ethereum.listener.EthereumListener;
|
||||||
import org.ethereum.manager.WorldManager;
|
import org.ethereum.manager.WorldManager;
|
||||||
import org.ethereum.net.client.ClientPeer;
|
import org.ethereum.net.client.ClientPeer;
|
||||||
|
@ -195,7 +195,7 @@ public class EthereumImpl implements Ethereum {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Repository getRepository(){
|
public RepositoryImpl getRepository(){
|
||||||
return WorldManager.getInstance().getRepository();
|
return WorldManager.getInstance().getRepository();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,6 @@ package org.ethereum.facade;
|
||||||
import org.ethereum.core.AccountState;
|
import org.ethereum.core.AccountState;
|
||||||
import org.ethereum.db.ContractDetails;
|
import org.ethereum.db.ContractDetails;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* www.ethereumJ.com
|
* www.ethereumJ.com
|
||||||
*
|
*
|
||||||
|
@ -16,5 +14,4 @@ public interface Repository {
|
||||||
|
|
||||||
public AccountState getAccountState(byte[] addr);
|
public AccountState getAccountState(byte[] addr);
|
||||||
public ContractDetails getContractDetails(byte[] addr);
|
public ContractDetails getContractDetails(byte[] addr);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import org.ethereum.core.AccountState;
|
||||||
import org.ethereum.core.Block;
|
import org.ethereum.core.Block;
|
||||||
import org.ethereum.db.ByteArrayWrapper;
|
import org.ethereum.db.ByteArrayWrapper;
|
||||||
import org.ethereum.db.ContractDetails;
|
import org.ethereum.db.ContractDetails;
|
||||||
import org.ethereum.db.Repository;
|
import org.ethereum.db.RepositoryImpl;
|
||||||
import org.ethereum.util.ByteUtil;
|
import org.ethereum.util.ByteUtil;
|
||||||
import org.ethereum.vm.DataWord;
|
import org.ethereum.vm.DataWord;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
@ -67,7 +67,7 @@ public class JSONHelper {
|
||||||
|
|
||||||
public static void dumpBlock(ObjectNode blockNode, Block block,
|
public static void dumpBlock(ObjectNode blockNode, Block block,
|
||||||
long gasUsed, byte[] state, List<ByteArrayWrapper> keys,
|
long gasUsed, byte[] state, List<ByteArrayWrapper> keys,
|
||||||
Repository repository) {
|
RepositoryImpl repository) {
|
||||||
|
|
||||||
blockNode.put("coinbase", Hex.toHexString(block.getCoinbase()));
|
blockNode.put("coinbase", Hex.toHexString(block.getCoinbase()));
|
||||||
blockNode.put("difficulty", new BigInteger(1, block.calcDifficulty()).toString());
|
blockNode.put("difficulty", new BigInteger(1, block.calcDifficulty()).toString());
|
||||||
|
|
|
@ -2,7 +2,7 @@ package org.ethereum.jsontestsuite;
|
||||||
|
|
||||||
import org.ethereum.db.ByteArrayWrapper;
|
import org.ethereum.db.ByteArrayWrapper;
|
||||||
import org.ethereum.db.ContractDetails;
|
import org.ethereum.db.ContractDetails;
|
||||||
import org.ethereum.db.Repository;
|
import org.ethereum.db.RepositoryImpl;
|
||||||
import org.ethereum.util.ByteUtil;
|
import org.ethereum.util.ByteUtil;
|
||||||
import org.ethereum.vm.*;
|
import org.ethereum.vm.*;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -46,7 +46,7 @@ public class TestRunner {
|
||||||
|
|
||||||
List<String> results = new ArrayList<>();
|
List<String> results = new ArrayList<>();
|
||||||
|
|
||||||
Repository repository = new Repository();
|
RepositoryImpl repository = new RepositoryImpl();
|
||||||
|
|
||||||
/* 1. Store pre-exist accounts - Pre */
|
/* 1. Store pre-exist accounts - Pre */
|
||||||
for (ByteArrayWrapper key : testCase.getPre().keySet()){
|
for (ByteArrayWrapper key : testCase.getPre().keySet()){
|
||||||
|
|
|
@ -2,17 +2,14 @@ package org.ethereum.manager;
|
||||||
|
|
||||||
import static org.ethereum.config.SystemProperties.CONFIG;
|
import static org.ethereum.config.SystemProperties.CONFIG;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import org.ethereum.core.AccountState;
|
import org.ethereum.core.BlockchainImpl;
|
||||||
import org.ethereum.core.Blockchain;
|
|
||||||
import org.ethereum.core.Wallet;
|
import org.ethereum.core.Wallet;
|
||||||
import org.ethereum.crypto.ECKey;
|
|
||||||
import org.ethereum.crypto.HashUtil;
|
import org.ethereum.crypto.HashUtil;
|
||||||
import org.ethereum.db.Repository;
|
import org.ethereum.db.RepositoryImpl;
|
||||||
import org.ethereum.listener.EthereumListener;
|
import org.ethereum.listener.EthereumListener;
|
||||||
import org.ethereum.net.client.ClientPeer;
|
import org.ethereum.net.client.ClientPeer;
|
||||||
import org.ethereum.net.client.PeerData;
|
import org.ethereum.net.client.PeerData;
|
||||||
|
@ -28,8 +25,8 @@ import org.ethereum.net.peerdiscovery.PeerDiscovery;
|
||||||
*/
|
*/
|
||||||
public class WorldManager {
|
public class WorldManager {
|
||||||
|
|
||||||
private Blockchain blockchain;
|
private BlockchainImpl blockchain;
|
||||||
private Repository repository;
|
private RepositoryImpl repository;
|
||||||
private Wallet wallet;
|
private Wallet wallet;
|
||||||
|
|
||||||
private PeerDiscovery peerDiscovery;
|
private PeerDiscovery peerDiscovery;
|
||||||
|
@ -48,8 +45,8 @@ public class WorldManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private WorldManager() {
|
private WorldManager() {
|
||||||
this.repository = new Repository();
|
this.repository = new RepositoryImpl();
|
||||||
this.blockchain = new Blockchain(repository);
|
this.blockchain = new BlockchainImpl(repository);
|
||||||
|
|
||||||
// Initialize PeerData
|
// Initialize PeerData
|
||||||
List<PeerData> peerDataList = parsePeerDiscoveryIpList(CONFIG.peerDiscoveryIPList());
|
List<PeerData> peerDataList = parsePeerDiscoveryIpList(CONFIG.peerDiscoveryIPList());
|
||||||
|
@ -60,17 +57,15 @@ public class WorldManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
// used for testing
|
// used for testing
|
||||||
public void reset(){
|
public void reset() {
|
||||||
|
this.repository = new RepositoryImpl();
|
||||||
this.repository = new Repository();
|
this.blockchain = new BlockchainImpl(repository);
|
||||||
this.blockchain = new Blockchain(repository);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init(){
|
public void init() {
|
||||||
this.wallet = new Wallet();
|
|
||||||
|
|
||||||
|
this.wallet = new Wallet();
|
||||||
byte[] cowAddr = HashUtil.sha3("cow".getBytes());
|
byte[] cowAddr = HashUtil.sha3("cow".getBytes());
|
||||||
ECKey key = ECKey.fromPrivate(cowAddr);
|
|
||||||
wallet.importKey(cowAddr);
|
wallet.importKey(cowAddr);
|
||||||
|
|
||||||
// AccountState state = wallet.getAccountState(key.getAddress());
|
// AccountState state = wallet.getAccountState(key.getAddress());
|
||||||
|
@ -79,20 +74,19 @@ public class WorldManager {
|
||||||
String secret = CONFIG.coinbaseSecret();
|
String secret = CONFIG.coinbaseSecret();
|
||||||
byte[] cbAddr = HashUtil.sha3(secret.getBytes());
|
byte[] cbAddr = HashUtil.sha3(secret.getBytes());
|
||||||
wallet.importKey(cbAddr);
|
wallet.importKey(cbAddr);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WorldManager getInstance() {
|
public static WorldManager getInstance() {
|
||||||
return WorldManagerHolder.instance;
|
return WorldManagerHolder.instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addListener(EthereumListener listener){
|
public void addListener(EthereumListener listener) {
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPeers(final Set<PeerData> newPeers) {
|
public void addPeers(final Set<PeerData> newPeers) {
|
||||||
|
|
||||||
synchronized (peers){
|
synchronized (peers) {
|
||||||
for (final PeerData peer : newPeers) {
|
for (final PeerData peer : newPeers) {
|
||||||
if (peerDiscovery.isStarted() && !peers.contains(peer)) {
|
if (peerDiscovery.isStarted() && !peers.contains(peer)) {
|
||||||
peerDiscovery.addNewPeerData(peer);
|
peerDiscovery.addNewPeerData(peer);
|
||||||
|
@ -149,11 +143,11 @@ public class WorldManager {
|
||||||
this.wallet = wallet;
|
this.wallet = wallet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Repository getRepository() {
|
public RepositoryImpl getRepository() {
|
||||||
return repository;
|
return repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Blockchain getBlockchain() {
|
public BlockchainImpl getBlockchain() {
|
||||||
return blockchain;
|
return blockchain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import org.spongycastle.util.Arrays;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,15 +42,12 @@ public class DataWord implements Comparable<DataWord> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataWord(byte[] data) {
|
public DataWord(byte[] data) {
|
||||||
|
if (data == null)
|
||||||
if (data == null) {
|
this.data = ByteUtil.EMPTY_BYTE_ARRAY;
|
||||||
this.data = new byte[] {};
|
else if (data.length <= 32)
|
||||||
return;
|
System.arraycopy(data, 0, this.data, 32 - data.length, data.length);
|
||||||
}
|
else
|
||||||
|
throw new RuntimeException("Data word can't exit 32 bytes: " + data);
|
||||||
if (data.length > 32)
|
|
||||||
throw new RuntimeException("Data word can't exit 32 bytes: " + data);
|
|
||||||
System.arraycopy(data, 0, this.data, 32 - data.length, data.length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getData() {
|
public byte[] getData() {
|
||||||
|
@ -67,12 +65,32 @@ public class DataWord implements Comparable<DataWord> {
|
||||||
return new BigInteger(1, data);
|
return new BigInteger(1, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this DataWord to an int, checking for lost information.
|
||||||
|
* If this DataWord is out of the possible range for an int result
|
||||||
|
* then an ArithmeticException is thrown.
|
||||||
|
*
|
||||||
|
* @return this DataWord converted to an int.
|
||||||
|
* @throws ArithmeticException - if this will not fit in an int.
|
||||||
|
*/
|
||||||
public int intValue() {
|
public int intValue() {
|
||||||
return new BigInteger(1, data).intValue();
|
// FIXME: Disabled for POC5
|
||||||
|
// BigDecimal tmpValue = new BigDecimal(this.value());
|
||||||
|
// return tmpValue.intValueExact();
|
||||||
|
return this.value().intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this DataWord to a long, checking for lost information.
|
||||||
|
* If this DataWord is out of the possible range for a long result
|
||||||
|
* then an ArithmeticException is thrown.
|
||||||
|
*
|
||||||
|
* @return this DataWord converted to a long.
|
||||||
|
* @throws ArithmeticException - if this will not fit in a long.
|
||||||
|
*/
|
||||||
public long longValue() {
|
public long longValue() {
|
||||||
return new BigInteger(1, data).longValue();
|
BigDecimal tmpValue = new BigDecimal(this.value());
|
||||||
|
return tmpValue.longValueExact();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigInteger sValue() {
|
public BigInteger sValue() {
|
||||||
|
@ -219,7 +237,7 @@ public class DataWord implements Comparable<DataWord> {
|
||||||
// TODO: improve with no BigInteger
|
// TODO: improve with no BigInteger
|
||||||
public void exp(DataWord word) {
|
public void exp(DataWord word) {
|
||||||
|
|
||||||
BigInteger result = value().pow(word.value().intValue());
|
BigInteger result = value().pow(word.intValue());
|
||||||
byte[] bytes = result.toByteArray();
|
byte[] bytes = result.toByteArray();
|
||||||
|
|
||||||
ByteBuffer data = ByteBuffer.allocate(32);
|
ByteBuffer data = ByteBuffer.allocate(32);
|
||||||
|
@ -300,4 +318,4 @@ public class DataWord implements Comparable<DataWord> {
|
||||||
data, 0, data.length,
|
data, 0, data.length,
|
||||||
o.getData(), 0, o.getData().length);
|
o.getData(), 0, o.getData().length);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@ package org.ethereum.vm;
|
||||||
|
|
||||||
import org.ethereum.crypto.HashUtil;
|
import org.ethereum.crypto.HashUtil;
|
||||||
import org.ethereum.db.ContractDetails;
|
import org.ethereum.db.ContractDetails;
|
||||||
import org.ethereum.db.Repository;
|
import org.ethereum.db.RepositoryImpl;
|
||||||
import org.ethereum.util.ByteUtil;
|
import org.ethereum.util.ByteUtil;
|
||||||
import org.ethereum.util.Utils;
|
import org.ethereum.util.Utils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -43,16 +43,17 @@ public class Program {
|
||||||
ProgramInvoke invokeData;
|
ProgramInvoke invokeData;
|
||||||
|
|
||||||
public Program(byte[] ops, ProgramInvoke invokeData) {
|
public Program(byte[] ops, ProgramInvoke invokeData) {
|
||||||
|
|
||||||
this.invokeHash = invokeData.hashCode();
|
if (ops == null) ops = ByteUtil.EMPTY_BYTE_ARRAY;
|
||||||
result.setRepository(invokeData.getRepository());
|
|
||||||
|
|
||||||
if (ops == null) ops = new byte[0]; //throw new RuntimeException("program can not run with ops: null");
|
|
||||||
|
|
||||||
this.invokeData = invokeData;
|
|
||||||
this.ops = ops;
|
this.ops = ops;
|
||||||
this.programAddress = invokeData.getOwnerAddress();
|
|
||||||
}
|
if (invokeData != null) {
|
||||||
|
this.invokeData = invokeData;
|
||||||
|
this.programAddress = invokeData.getOwnerAddress();
|
||||||
|
this.invokeHash = invokeData.hashCode();
|
||||||
|
this.result.setRepository(invokeData.getRepository());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public byte getCurrentOp() {
|
public byte getCurrentOp() {
|
||||||
if(ops.length == 0)
|
if(ops.length == 0)
|
||||||
|
@ -93,7 +94,7 @@ public class Program {
|
||||||
|
|
||||||
public void setPC(DataWord pc) {
|
public void setPC(DataWord pc) {
|
||||||
|
|
||||||
this.pc = pc.value().intValue();
|
this.pc = pc.intValue();
|
||||||
|
|
||||||
if (this.pc == ops.length) {
|
if (this.pc == ops.length) {
|
||||||
stop();
|
stop();
|
||||||
|
@ -162,71 +163,79 @@ public class Program {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void memorySave(DataWord addrB, DataWord value) {
|
public void memorySave(DataWord addrB, DataWord value) {
|
||||||
memorySave(addrB.getData(), value.getData());
|
memorySave(addrB.intValue(), value.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void memorySave(byte[] addr, byte[] value) {
|
public void memorySave(int addr, byte[] value) {
|
||||||
|
memorySave(addr, value.length, value);
|
||||||
int address = new BigInteger(1, addr).intValue();
|
|
||||||
allocateMemory(address, value);
|
|
||||||
System.arraycopy(value, 0, memory.array(), address, value.length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates a piece of memory and stores value at given offset address
|
||||||
|
*
|
||||||
|
* @param addr is the offset address
|
||||||
|
* @param allocSize size of memory needed to write
|
||||||
|
* @param value the data to write to memory
|
||||||
|
*/
|
||||||
|
public void memorySave(int addr, int allocSize, byte[] value) {
|
||||||
|
|
||||||
|
allocateMemory(addr, allocSize);
|
||||||
|
System.arraycopy(value, 0, memory.array(), addr, value.length);
|
||||||
|
}
|
||||||
|
|
||||||
public DataWord memoryLoad(DataWord addr) {
|
public DataWord memoryLoad(DataWord addr) {
|
||||||
|
return memoryLoad(addr.intValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataWord memoryLoad(int address) {
|
||||||
|
|
||||||
int address = new BigInteger(1, addr.getData()).intValue();
|
allocateMemory(address, DataWord.ZERO.getData().length);
|
||||||
allocateMemory(address, DataWord.ZERO.getData());
|
|
||||||
|
|
||||||
byte[] data = new byte[32];
|
DataWord newMem = new DataWord();
|
||||||
System.arraycopy(memory.array(), address, data , 0 ,32);
|
System.arraycopy(memory.array(), address, newMem.getData(), 0, newMem.getData().length);
|
||||||
|
|
||||||
return new DataWord(data);
|
return newMem;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer memoryChunk(DataWord offsetData, DataWord sizeData) {
|
public ByteBuffer memoryChunk(DataWord offsetData, DataWord sizeData) {
|
||||||
|
return memoryChunk(offsetData.intValue(), sizeData.intValue());
|
||||||
|
}
|
||||||
|
|
||||||
int offset = offsetData.intValue();
|
/**
|
||||||
int size = sizeData.intValue();
|
* Returns a piece of memory from a given offset and specified size
|
||||||
byte[] chunk = new byte[size];
|
* If the offset + size exceed the current memory-size,
|
||||||
allocateMemory(offset, new byte[size]);
|
* the remainder will be filled with empty bytes.
|
||||||
|
*
|
||||||
|
* @param offset byte address in memory
|
||||||
|
* @param size the amount of bytes to return
|
||||||
|
* @return ByteBuffer containing the chunk of memory data
|
||||||
|
*/
|
||||||
|
public ByteBuffer memoryChunk(int offset, int size) {
|
||||||
|
|
||||||
if (memory != null) {
|
allocateMemory(offset, size);
|
||||||
if (memory.limit() < offset + size) size = memory.limit() - offset;
|
byte[] chunk;
|
||||||
System.arraycopy(memory.array(), offset, chunk, 0, size);
|
if (memory != null)
|
||||||
}
|
chunk = Arrays.copyOfRange(memory.array(), offset, offset+size);
|
||||||
|
else
|
||||||
|
chunk = new byte[size];
|
||||||
return ByteBuffer.wrap(chunk);
|
return ByteBuffer.wrap(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void allocateMemory(int address, byte[] value) {
|
/**
|
||||||
|
* Allocates extra memory in the program for
|
||||||
|
* a specified size, calculated from a given offset
|
||||||
|
*
|
||||||
|
* @param offset the memory address offset
|
||||||
|
* @param size the number of bytes to allocate
|
||||||
|
*/
|
||||||
|
protected void allocateMemory(int offset, int size) {
|
||||||
|
|
||||||
int memSize = 0;
|
int memSize = memory != null ? memory.limit(): 0;
|
||||||
if (memory != null) memSize = memory.limit();
|
double newMemSize = Math.max(memSize, Math.ceil((double)(offset + size) / 32) * 32);
|
||||||
|
ByteBuffer tmpMem = ByteBuffer.allocate((int)newMemSize);
|
||||||
// check if you need to allocate
|
if (memory != null)
|
||||||
if (memSize < (address + value.length)) {
|
tmpMem.put(memory.array(), 0, memory.limit());
|
||||||
|
memory = tmpMem;
|
||||||
long overlap = memSize - address;
|
|
||||||
|
|
||||||
int sizeToAllocate = 0;
|
|
||||||
if (memSize > address) {
|
|
||||||
sizeToAllocate = memSize + value.length;
|
|
||||||
} else {
|
|
||||||
sizeToAllocate = memSize + (address - memSize) + value.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (overlap > 0) sizeToAllocate -= overlap;
|
|
||||||
|
|
||||||
// complete to 32
|
|
||||||
sizeToAllocate = (sizeToAllocate % 32)==0 ? sizeToAllocate :
|
|
||||||
sizeToAllocate + (32 - sizeToAllocate % 32);
|
|
||||||
sizeToAllocate = (sizeToAllocate == 0)? 32: sizeToAllocate;
|
|
||||||
|
|
||||||
ByteBuffer tmpMem = ByteBuffer.allocate(sizeToAllocate);
|
|
||||||
if (memory != null)
|
|
||||||
System.arraycopy(memory.array(), 0, tmpMem.array(), 0, memory.limit());
|
|
||||||
|
|
||||||
memory = tmpMem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void suicide(DataWord obtainer) {
|
public void suicide(DataWord obtainer) {
|
||||||
|
@ -282,13 +291,13 @@ public class Program {
|
||||||
result.getRepository().addBalance(senderAddress, endowment.negate());
|
result.getRepository().addBalance(senderAddress, endowment.negate());
|
||||||
result.getRepository().addBalance(newAddress, endowment);
|
result.getRepository().addBalance(newAddress, endowment);
|
||||||
|
|
||||||
Repository trackRepository = result.getRepository().getTrack();
|
RepositoryImpl trackRepositoryImpl = result.getRepository().getTrack();
|
||||||
trackRepository.startTracking();
|
trackRepositoryImpl.startTracking();
|
||||||
|
|
||||||
// [5] COOK THE INVOKE AND EXECUTE
|
// [5] COOK THE INVOKE AND EXECUTE
|
||||||
ProgramInvoke programInvoke =
|
ProgramInvoke programInvoke =
|
||||||
ProgramInvokeFactory.createProgramInvoke(this, new DataWord(newAddress), DataWord.ZERO,
|
ProgramInvokeFactory.createProgramInvoke(this, new DataWord(newAddress), DataWord.ZERO,
|
||||||
new DataWord(gas), BigInteger.ZERO, null, trackRepository, this.invokeData.getCallDeep() + 1);
|
new DataWord(gas), BigInteger.ZERO, null, trackRepositoryImpl, this.invokeData.getCallDeep() + 1);
|
||||||
|
|
||||||
VM vm = new VM();
|
VM vm = new VM();
|
||||||
Program program = new Program(programCode.array(), programInvoke);
|
Program program = new Program(programCode.array(), programInvoke);
|
||||||
|
@ -300,18 +309,18 @@ public class Program {
|
||||||
result.getException() instanceof Program.OutOfGasException) {
|
result.getException() instanceof Program.OutOfGasException) {
|
||||||
logger.info("contract run halted by OutOfGas: new contract init ={}" , Hex.toHexString(newAddress));
|
logger.info("contract run halted by OutOfGas: new contract init ={}" , Hex.toHexString(newAddress));
|
||||||
|
|
||||||
trackRepository.rollback();
|
trackRepositoryImpl.rollback();
|
||||||
stackPushZero();
|
stackPushZero();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. CREATE THE CONTRACT OUT OF RETURN
|
// 4. CREATE THE CONTRACT OUT OF RETURN
|
||||||
byte[] code = result.getHReturn().array();
|
byte[] code = result.getHReturn().array();
|
||||||
trackRepository.saveCode(newAddress, code);
|
trackRepositoryImpl.saveCode(newAddress, code);
|
||||||
|
|
||||||
// IN SUCCESS PUSH THE ADDRESS INTO THE STACK
|
// IN SUCCESS PUSH THE ADDRESS INTO THE STACK
|
||||||
stackPush(new DataWord(newAddress));
|
stackPush(new DataWord(newAddress));
|
||||||
trackRepository.commit();
|
trackRepositoryImpl.commit();
|
||||||
|
|
||||||
// 5. REFUND THE REMAIN GAS
|
// 5. REFUND THE REMAIN GAS
|
||||||
long refundGas = gas - result.getGasUsed();
|
long refundGas = gas - result.getGasUsed();
|
||||||
|
@ -388,15 +397,15 @@ public class Program {
|
||||||
// actual gas subtract
|
// actual gas subtract
|
||||||
this.spendGas(gas.intValue(), "internal call");
|
this.spendGas(gas.intValue(), "internal call");
|
||||||
|
|
||||||
Repository trackRepository = result.getRepository().getTrack();
|
RepositoryImpl trackRepositoryImpl = result.getRepository().getTrack();
|
||||||
trackRepository.startTracking();
|
trackRepositoryImpl.startTracking();
|
||||||
trackRepository.addBalance(toAddress, endowmentValue.value());
|
trackRepositoryImpl.addBalance(toAddress, endowmentValue.value());
|
||||||
|
|
||||||
ProgramInvoke programInvoke =
|
ProgramInvoke programInvoke =
|
||||||
ProgramInvokeFactory.createProgramInvoke(this, toAddressDW,
|
ProgramInvokeFactory.createProgramInvoke(this, toAddressDW,
|
||||||
endowmentValue, gas, result.getRepository().getBalance(toAddress),
|
endowmentValue, gas, result.getRepository().getBalance(toAddress),
|
||||||
data.array(),
|
data.array(),
|
||||||
trackRepository, this.invokeData.getCallDeep() + 1);
|
trackRepositoryImpl, this.invokeData.getCallDeep() + 1);
|
||||||
|
|
||||||
ProgramResult result = null;
|
ProgramResult result = null;
|
||||||
|
|
||||||
|
@ -413,7 +422,7 @@ public class Program {
|
||||||
result.getException() instanceof Program.OutOfGasException) {
|
result.getException() instanceof Program.OutOfGasException) {
|
||||||
logger.info("contract run halted by OutOfGas: contract={}" , Hex.toHexString(toAddress));
|
logger.info("contract run halted by OutOfGas: contract={}" , Hex.toHexString(toAddress));
|
||||||
|
|
||||||
trackRepository.rollback();
|
trackRepositoryImpl.rollback();
|
||||||
stackPushZero();
|
stackPushZero();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -421,24 +430,20 @@ public class Program {
|
||||||
// 3. APPLY RESULTS: result.getHReturn() into out_memory allocated
|
// 3. APPLY RESULTS: result.getHReturn() into out_memory allocated
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
ByteBuffer buffer = result.getHReturn();
|
ByteBuffer buffer = result.getHReturn();
|
||||||
if (buffer != null) {
|
int allocSize = outDataSize.intValue();
|
||||||
int retSize = buffer.array().length;
|
if (buffer != null && allocSize > 0) {
|
||||||
int allocSize = outDataSize.intValue();
|
int retSize = buffer.limit();
|
||||||
|
int offset = outDataOffs.intValue();
|
||||||
if (retSize > allocSize) {
|
if (retSize > allocSize) {
|
||||||
byte[] outArray = Arrays.copyOf(buffer.array(), allocSize);
|
this.memorySave(offset, buffer.array());
|
||||||
this.memorySave(outArray, buffer.array());
|
|
||||||
} else if (retSize == 0 || retSize == allocSize){
|
|
||||||
this.memorySave(outDataOffs.getData(), buffer.array());
|
|
||||||
} else {
|
} else {
|
||||||
byte[] outArray = new byte[allocSize];
|
this.memorySave(offset, allocSize, buffer.array());
|
||||||
System.arraycopy(buffer.array(), 0, outArray, 0, retSize);
|
|
||||||
this.memorySave(outDataOffs.getData(), outArray);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. THE FLAG OF SUCCESS IS ONE PUSHED INTO THE STACK
|
// 4. THE FLAG OF SUCCESS IS ONE PUSHED INTO THE STACK
|
||||||
trackRepository.commit();
|
trackRepositoryImpl.commit();
|
||||||
stackPushOne();
|
stackPushOne();
|
||||||
|
|
||||||
// 5. REFUND THE REMAIN GAS
|
// 5. REFUND THE REMAIN GAS
|
||||||
|
@ -702,4 +707,4 @@ public class Program {
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class OutOfGasException extends RuntimeException {
|
public class OutOfGasException extends RuntimeException {
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
package org.ethereum.vm;
|
package org.ethereum.vm;
|
||||||
|
|
||||||
import org.ethereum.db.Repository;
|
import org.ethereum.db.RepositoryImpl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* www.ethereumJ.com
|
* www.ethereumJ.com
|
||||||
|
@ -27,7 +27,7 @@ public interface ProgramInvoke {
|
||||||
public DataWord getDifficulty();
|
public DataWord getDifficulty();
|
||||||
public DataWord getGaslimit();
|
public DataWord getGaslimit();
|
||||||
|
|
||||||
public Repository getRepository();
|
public RepositoryImpl getRepository();
|
||||||
|
|
||||||
public boolean byTransaction();
|
public boolean byTransaction();
|
||||||
boolean byTestingSuite();
|
boolean byTestingSuite();
|
||||||
|
|
|
@ -2,7 +2,7 @@ package org.ethereum.vm;
|
||||||
|
|
||||||
import org.ethereum.core.Block;
|
import org.ethereum.core.Block;
|
||||||
import org.ethereum.core.Transaction;
|
import org.ethereum.core.Transaction;
|
||||||
import org.ethereum.db.Repository;
|
import org.ethereum.db.RepositoryImpl;
|
||||||
import org.ethereum.manager.WorldManager;
|
import org.ethereum.manager.WorldManager;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -21,7 +21,7 @@ public class ProgramInvokeFactory {
|
||||||
private static Logger logger = LoggerFactory.getLogger("VM");
|
private static Logger logger = LoggerFactory.getLogger("VM");
|
||||||
|
|
||||||
// Invocation by the wire tx
|
// Invocation by the wire tx
|
||||||
public static ProgramInvoke createProgramInvoke(Transaction tx, Block block, Repository repository) {
|
public static ProgramInvoke createProgramInvoke(Transaction tx, Block block, RepositoryImpl repository) {
|
||||||
|
|
||||||
// https://ethereum.etherpad.mozilla.org/26
|
// https://ethereum.etherpad.mozilla.org/26
|
||||||
Block lastBlock = WorldManager.getInstance().getBlockchain().getLastBlock();
|
Block lastBlock = WorldManager.getInstance().getBlockchain().getLastBlock();
|
||||||
|
@ -122,7 +122,7 @@ public class ProgramInvokeFactory {
|
||||||
public static ProgramInvoke createProgramInvoke(Program program, DataWord toAddress,
|
public static ProgramInvoke createProgramInvoke(Program program, DataWord toAddress,
|
||||||
DataWord inValue, DataWord inGas,
|
DataWord inValue, DataWord inGas,
|
||||||
BigInteger balanceInt, byte[] dataIn,
|
BigInteger balanceInt, byte[] dataIn,
|
||||||
Repository repository, int callDeep) {
|
RepositoryImpl repository, int callDeep) {
|
||||||
|
|
||||||
DataWord address = toAddress;
|
DataWord address = toAddress;
|
||||||
DataWord origin = program.getOriginAddress();
|
DataWord origin = program.getOriginAddress();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package org.ethereum.vm;
|
package org.ethereum.vm;
|
||||||
|
|
||||||
import org.ethereum.db.Repository;
|
import org.ethereum.db.RepositoryImpl;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -26,7 +26,7 @@ public class ProgramInvokeImpl implements ProgramInvoke {
|
||||||
|
|
||||||
Map<DataWord, DataWord> storage;
|
Map<DataWord, DataWord> storage;
|
||||||
|
|
||||||
private Repository repository;
|
private RepositoryImpl repository;
|
||||||
private boolean byTransaction = true;
|
private boolean byTransaction = true;
|
||||||
private boolean byTestingSuite = false;
|
private boolean byTestingSuite = false;
|
||||||
private int callDeep = 0;
|
private int callDeep = 0;
|
||||||
|
@ -34,7 +34,7 @@ public class ProgramInvokeImpl implements ProgramInvoke {
|
||||||
public ProgramInvokeImpl(DataWord address, DataWord origin, DataWord caller, DataWord balance,
|
public ProgramInvokeImpl(DataWord address, DataWord origin, DataWord caller, DataWord balance,
|
||||||
DataWord gasPrice, DataWord gas, DataWord callValue, byte[] msgData,
|
DataWord gasPrice, DataWord gas, DataWord callValue, byte[] msgData,
|
||||||
DataWord lastHash, DataWord coinbase, DataWord timestamp, DataWord number, DataWord difficulty,
|
DataWord lastHash, DataWord coinbase, DataWord timestamp, DataWord number, DataWord difficulty,
|
||||||
DataWord gaslimit, Repository repository, int callDeep) {
|
DataWord gaslimit, RepositoryImpl repository, int callDeep) {
|
||||||
|
|
||||||
// Transaction env
|
// Transaction env
|
||||||
this.address = address;
|
this.address = address;
|
||||||
|
@ -63,7 +63,7 @@ public class ProgramInvokeImpl implements ProgramInvoke {
|
||||||
byte[] gasPrice, byte[] gas, byte[] callValue, byte[] msgData,
|
byte[] gasPrice, byte[] gas, byte[] callValue, byte[] msgData,
|
||||||
byte[] lastHash, byte[] coinbase, long timestamp, long number, byte[] difficulty,
|
byte[] lastHash, byte[] coinbase, long timestamp, long number, byte[] difficulty,
|
||||||
long gaslimit,
|
long gaslimit,
|
||||||
Repository repository, boolean byTestingSuite) {
|
RepositoryImpl repository, boolean byTestingSuite) {
|
||||||
this(address, origin, caller, balance, gasPrice, gas, callValue, msgData, lastHash, coinbase,
|
this(address, origin, caller, balance, gasPrice, gas, callValue, msgData, lastHash, coinbase,
|
||||||
timestamp, number, difficulty, gaslimit, repository);
|
timestamp, number, difficulty, gaslimit, repository);
|
||||||
this.byTestingSuite = byTestingSuite;
|
this.byTestingSuite = byTestingSuite;
|
||||||
|
@ -74,7 +74,7 @@ public class ProgramInvokeImpl implements ProgramInvoke {
|
||||||
byte[] gasPrice, byte[] gas, byte[] callValue, byte[] msgData,
|
byte[] gasPrice, byte[] gas, byte[] callValue, byte[] msgData,
|
||||||
byte[] lastHash, byte[] coinbase, long timestamp, long number, byte[] difficulty,
|
byte[] lastHash, byte[] coinbase, long timestamp, long number, byte[] difficulty,
|
||||||
long gaslimit,
|
long gaslimit,
|
||||||
Repository repository) {
|
RepositoryImpl repository) {
|
||||||
|
|
||||||
// Transaction env
|
// Transaction env
|
||||||
this.address = new DataWord(address);
|
this.address = new DataWord(address);
|
||||||
|
@ -215,7 +215,7 @@ public class ProgramInvokeImpl implements ProgramInvoke {
|
||||||
/* Storage */
|
/* Storage */
|
||||||
public Map<DataWord, DataWord> getStorage() { return storage; }
|
public Map<DataWord, DataWord> getStorage() { return storage; }
|
||||||
|
|
||||||
public Repository getRepository() {
|
public RepositoryImpl getRepository() {
|
||||||
return repository;
|
return repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ package org.ethereum.vm;
|
||||||
|
|
||||||
import org.ethereum.crypto.ECKey;
|
import org.ethereum.crypto.ECKey;
|
||||||
import org.ethereum.crypto.HashUtil;
|
import org.ethereum.crypto.HashUtil;
|
||||||
import org.ethereum.db.Repository;
|
import org.ethereum.db.RepositoryImpl;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,7 +15,7 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
|
||||||
private byte[] msgData;
|
private byte[] msgData;
|
||||||
|
|
||||||
|
|
||||||
private Repository repository = null;
|
private RepositoryImpl repository = null;
|
||||||
private String ownerAddress = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
private String ownerAddress = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||||
|
|
||||||
public ProgramInvokeMockImpl(byte[] msgDataRaw) {
|
public ProgramInvokeMockImpl(byte[] msgDataRaw) {
|
||||||
|
@ -24,7 +24,7 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProgramInvokeMockImpl() {
|
public ProgramInvokeMockImpl() {
|
||||||
this.repository = new Repository();
|
this.repository = new RepositoryImpl();
|
||||||
this.repository.createAccount(Hex.decode(ownerAddress));
|
this.repository.createAccount(Hex.decode(ownerAddress));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,11 +179,11 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Repository getRepository() {
|
public RepositoryImpl getRepository() {
|
||||||
return this.repository;
|
return this.repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRepository(Repository repository) {
|
public void setRepository(RepositoryImpl repository) {
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package org.ethereum.vm;
|
package org.ethereum.vm;
|
||||||
|
|
||||||
import org.ethereum.db.Repository;
|
import org.ethereum.db.RepositoryImpl;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -18,7 +18,7 @@ public class ProgramResult {
|
||||||
private RuntimeException exception;
|
private RuntimeException exception;
|
||||||
private List<DataWord> deleteAccounts;
|
private List<DataWord> deleteAccounts;
|
||||||
|
|
||||||
private Repository repository = null;
|
private RepositoryImpl repository = null;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* for testing runs ,
|
* for testing runs ,
|
||||||
|
@ -55,11 +55,11 @@ public class ProgramResult {
|
||||||
this.exception = exception;
|
this.exception = exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Repository getRepository() {
|
public RepositoryImpl getRepository() {
|
||||||
return repository;
|
return repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRepository(Repository repository) {
|
public void setRepository(RepositoryImpl repository) {
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,8 +144,8 @@ public class VM {
|
||||||
}
|
}
|
||||||
callGas = callGasWord.longValue();
|
callGas = callGasWord.longValue();
|
||||||
// Casting to long (causing overflow) as workaround for PoC5 - should be removed for PoC6
|
// Casting to long (causing overflow) as workaround for PoC5 - should be removed for PoC6
|
||||||
long x = stack.get(stack.size()-6).value().add(stack.get(stack.size()-7).value()).longValue();
|
long x = stack.get(stack.size()-4).value().add(stack.get(stack.size()-5).value()).longValue(); // in offset+size
|
||||||
long y = stack.get(stack.size()-4).value().add(stack.get(stack.size()-5).value()).longValue();
|
long y = stack.get(stack.size()-6).value().add(stack.get(stack.size()-7).value()).longValue(); // out offset+size
|
||||||
newMemSize = BigInteger.valueOf(Math.max(x, y));
|
newMemSize = BigInteger.valueOf(Math.max(x, y));
|
||||||
break;
|
break;
|
||||||
case CREATE:
|
case CREATE:
|
||||||
|
@ -157,6 +157,7 @@ public class VM {
|
||||||
}
|
}
|
||||||
program.spendGas(gasCost, op.name());
|
program.spendGas(gasCost, op.name());
|
||||||
|
|
||||||
|
// Avoid overflows
|
||||||
if(newMemSize.compareTo(MAX_GAS) == 1) {
|
if(newMemSize.compareTo(MAX_GAS) == 1) {
|
||||||
throw program.new OutOfGasException();
|
throw program.new OutOfGasException();
|
||||||
}
|
}
|
||||||
|
@ -422,7 +423,7 @@ public class VM {
|
||||||
DataWord word2 = program.stackPop();
|
DataWord word2 = program.stackPop();
|
||||||
DataWord result = null;
|
DataWord result = null;
|
||||||
if (word1.value().compareTo(_32_) == -1) {
|
if (word1.value().compareTo(_32_) == -1) {
|
||||||
byte tmp = word2.getData()[word1.value().intValue()];
|
byte tmp = word2.getData()[word1.intValue()];
|
||||||
word2.and(DataWord.ZERO);
|
word2.and(DataWord.ZERO);
|
||||||
word2.getData()[31] = tmp;
|
word2.getData()[31] = tmp;
|
||||||
result = word2;
|
result = word2;
|
||||||
|
@ -535,7 +536,7 @@ public class VM {
|
||||||
if (logger.isInfoEnabled())
|
if (logger.isInfoEnabled())
|
||||||
hint = "data: " + Hex.toHexString(msgData);
|
hint = "data: " + Hex.toHexString(msgData);
|
||||||
|
|
||||||
program.memorySave(memOffsetData.getData(), msgData);
|
program.memorySave(memOffsetData.intValue(), msgData);
|
||||||
program.step();
|
program.step();
|
||||||
} break;
|
} break;
|
||||||
case CODESIZE:{
|
case CODESIZE:{
|
||||||
|
@ -552,8 +553,8 @@ public class VM {
|
||||||
DataWord codeOffsetData = program.stackPop();
|
DataWord codeOffsetData = program.stackPop();
|
||||||
DataWord lengthData = program.stackPop();
|
DataWord lengthData = program.stackPop();
|
||||||
|
|
||||||
int length = lengthData.value().intValue();
|
int length = lengthData.intValue();
|
||||||
int codeOffset = codeOffsetData.value().intValue();
|
int codeOffset = codeOffsetData.intValue();
|
||||||
|
|
||||||
if (program.ops.length < length + codeOffset) {
|
if (program.ops.length < length + codeOffset) {
|
||||||
program.stop();
|
program.stop();
|
||||||
|
@ -566,7 +567,7 @@ public class VM {
|
||||||
if (logger.isInfoEnabled())
|
if (logger.isInfoEnabled())
|
||||||
hint = "code: " + Hex.toHexString(code);
|
hint = "code: " + Hex.toHexString(code);
|
||||||
|
|
||||||
program.memorySave(memOffsetData.getData(), code);
|
program.memorySave(memOffsetData.intValue(), code);
|
||||||
program.step();
|
program.step();
|
||||||
} break;
|
} break;
|
||||||
case GASPRICE:{
|
case GASPRICE:{
|
||||||
|
@ -678,7 +679,7 @@ public class VM {
|
||||||
DataWord addr = program.stackPop();
|
DataWord addr = program.stackPop();
|
||||||
DataWord value = program.stackPop();
|
DataWord value = program.stackPop();
|
||||||
byte[] byteVal = {value.getData()[31]};
|
byte[] byteVal = {value.getData()[31]};
|
||||||
program.memorySave(addr.getData(), byteVal);
|
program.memorySave(addr.intValue(), byteVal);
|
||||||
program.step();
|
program.step();
|
||||||
} break;
|
} break;
|
||||||
case SLOAD:{
|
case SLOAD:{
|
||||||
|
@ -938,4 +939,4 @@ public class VM {
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
private class IllegalOperationException extends RuntimeException {}
|
private class IllegalOperationException extends RuntimeException {}
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@ package org.ethereum.core;
|
||||||
|
|
||||||
import org.ethereum.crypto.ECKey;
|
import org.ethereum.crypto.ECKey;
|
||||||
import org.ethereum.crypto.HashUtil;
|
import org.ethereum.crypto.HashUtil;
|
||||||
import org.ethereum.db.Repository;
|
import org.ethereum.db.RepositoryImpl;
|
||||||
import org.ethereum.manager.WorldManager;
|
import org.ethereum.manager.WorldManager;
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
import org.junit.runners.MethodSorters;
|
import org.junit.runners.MethodSorters;
|
||||||
|
@ -37,7 +37,7 @@ public class WalletTest {
|
||||||
@Test // Testing account for simple balance set
|
@Test // Testing account for simple balance set
|
||||||
public void accountTest_1(){
|
public void accountTest_1(){
|
||||||
|
|
||||||
Repository repository = WorldManager.getInstance().getRepository();
|
RepositoryImpl repository = WorldManager.getInstance().getRepository();
|
||||||
|
|
||||||
ECKey cowKey = ECKey.fromPrivate(HashUtil.sha3("cow".getBytes()));
|
ECKey cowKey = ECKey.fromPrivate(HashUtil.sha3("cow".getBytes()));
|
||||||
repository.createAccount(cowKey.getAddress());
|
repository.createAccount(cowKey.getAddress());
|
||||||
|
@ -55,7 +55,7 @@ public class WalletTest {
|
||||||
@Test // test account balance with pending "unblocked" transaction
|
@Test // test account balance with pending "unblocked" transaction
|
||||||
public void accountTest_2(){
|
public void accountTest_2(){
|
||||||
|
|
||||||
Repository repository = WorldManager.getInstance().getRepository();
|
RepositoryImpl repository = WorldManager.getInstance().getRepository();
|
||||||
|
|
||||||
ECKey cowKey = ECKey.fromPrivate(HashUtil.sha3("cow".getBytes()));
|
ECKey cowKey = ECKey.fromPrivate(HashUtil.sha3("cow".getBytes()));
|
||||||
repository.createAccount(cowKey.getAddress());
|
repository.createAccount(cowKey.getAddress());
|
||||||
|
|
|
@ -23,7 +23,7 @@ public class RepositoryTest {
|
||||||
public void test1() {
|
public void test1() {
|
||||||
|
|
||||||
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||||
Repository repository = new Repository();
|
RepositoryImpl repository = new RepositoryImpl();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
AccountState createdState = repository.createAccount(Hex.decode(addr));
|
AccountState createdState = repository.createAccount(Hex.decode(addr));
|
||||||
|
@ -38,7 +38,7 @@ public class RepositoryTest {
|
||||||
public void test2() {
|
public void test2() {
|
||||||
|
|
||||||
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||||
Repository repository = new Repository();
|
RepositoryImpl repository = new RepositoryImpl();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
BigInteger nonce0 = repository.getNonce(Hex.decode(addr));
|
BigInteger nonce0 = repository.getNonce(Hex.decode(addr));
|
||||||
|
@ -61,7 +61,7 @@ public class RepositoryTest {
|
||||||
public void test3() {
|
public void test3() {
|
||||||
|
|
||||||
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||||
Repository repository = new Repository();
|
RepositoryImpl repository = new RepositoryImpl();
|
||||||
try {
|
try {
|
||||||
BigInteger nonce0 = repository.getNonce(Hex.decode(addr));
|
BigInteger nonce0 = repository.getNonce(Hex.decode(addr));
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ public class RepositoryTest {
|
||||||
public void test4() {
|
public void test4() {
|
||||||
|
|
||||||
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||||
Repository repository = new Repository();
|
RepositoryImpl repository = new RepositoryImpl();
|
||||||
try {
|
try {
|
||||||
BigInteger balance0 = repository.getBalance(Hex.decode(addr));
|
BigInteger balance0 = repository.getBalance(Hex.decode(addr));
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ public class RepositoryTest {
|
||||||
public void test5() {
|
public void test5() {
|
||||||
|
|
||||||
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||||
Repository repository = new Repository();
|
RepositoryImpl repository = new RepositoryImpl();
|
||||||
try {
|
try {
|
||||||
BigInteger balance0 = repository.getBalance(Hex.decode(addr));
|
BigInteger balance0 = repository.getBalance(Hex.decode(addr));
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ public class RepositoryTest {
|
||||||
public void test6() {
|
public void test6() {
|
||||||
|
|
||||||
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||||
Repository repository = new Repository();
|
RepositoryImpl repository = new RepositoryImpl();
|
||||||
|
|
||||||
byte[] code;
|
byte[] code;
|
||||||
try {
|
try {
|
||||||
|
@ -151,7 +151,7 @@ public class RepositoryTest {
|
||||||
String codeString = "7f60c860005461012c602054000000000000000000000000000000000000000000600060206000f200";
|
String codeString = "7f60c860005461012c602054000000000000000000000000000000000000000000600060206000f200";
|
||||||
String codeHash = "8f0d7fc8cc6fdd688fa58ae9256310069f5659ed2a8a3af994d80350fbf1e798";
|
String codeHash = "8f0d7fc8cc6fdd688fa58ae9256310069f5659ed2a8a3af994d80350fbf1e798";
|
||||||
|
|
||||||
Repository repository = new Repository();
|
RepositoryImpl repository = new RepositoryImpl();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
byte[] code0 = repository.getCode(Hex.decode(addr));
|
byte[] code0 = repository.getCode(Hex.decode(addr));
|
||||||
|
@ -174,7 +174,7 @@ public class RepositoryTest {
|
||||||
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||||
String codeHash = "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470";
|
String codeHash = "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470";
|
||||||
|
|
||||||
Repository repository = new Repository();
|
RepositoryImpl repository = new RepositoryImpl();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
byte[] code0 = repository.getCode(Hex.decode(addr));
|
byte[] code0 = repository.getCode(Hex.decode(addr));
|
||||||
|
@ -197,7 +197,7 @@ public class RepositoryTest {
|
||||||
byte[] keyBytes = Hex.decode("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
|
byte[] keyBytes = Hex.decode("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
|
||||||
DataWord key = new DataWord(keyBytes);
|
DataWord key = new DataWord(keyBytes);
|
||||||
|
|
||||||
Repository repository = new Repository();
|
RepositoryImpl repository = new RepositoryImpl();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
DataWord value = repository.getStorageValue(Hex.decode(addr), key);
|
DataWord value = repository.getStorageValue(Hex.decode(addr), key);
|
||||||
|
@ -211,7 +211,7 @@ public class RepositoryTest {
|
||||||
public void test10() {
|
public void test10() {
|
||||||
|
|
||||||
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||||
Repository repository = new Repository();
|
RepositoryImpl repository = new RepositoryImpl();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
repository.createAccount(Hex.decode(addr));
|
repository.createAccount(Hex.decode(addr));
|
||||||
|
@ -233,7 +233,7 @@ public class RepositoryTest {
|
||||||
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||||
String expectedStorageHash = "a737c40a4aa895fb9eb464536c376ee7c2c08eb733c8fd2353fcc62dc734f075";
|
String expectedStorageHash = "a737c40a4aa895fb9eb464536c376ee7c2c08eb733c8fd2353fcc62dc734f075";
|
||||||
|
|
||||||
Repository repository = new Repository();
|
RepositoryImpl repository = new RepositoryImpl();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
repository.createAccount(Hex.decode(addr));
|
repository.createAccount(Hex.decode(addr));
|
||||||
|
@ -283,10 +283,10 @@ public class RepositoryTest {
|
||||||
String expectedStorageHash = "365ed874ad42c2b4af335212465291e03dcd1f0c5b600f40f048ed238ad61fd3";
|
String expectedStorageHash = "365ed874ad42c2b4af335212465291e03dcd1f0c5b600f40f048ed238ad61fd3";
|
||||||
long expectedBalance = 333;
|
long expectedBalance = 333;
|
||||||
|
|
||||||
Repository origRepository = new Repository();
|
RepositoryImpl origRepository = new RepositoryImpl();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Repository repository = origRepository.getTrack();
|
RepositoryImpl repository = origRepository.getTrack();
|
||||||
repository.startTracking();
|
repository.startTracking();
|
||||||
|
|
||||||
repository.createAccount(Hex.decode(addr));
|
repository.createAccount(Hex.decode(addr));
|
||||||
|
@ -310,8 +310,8 @@ public class RepositoryTest {
|
||||||
long expectedBalance_1 = 55500;
|
long expectedBalance_1 = 55500;
|
||||||
long expectedBalance_2 = 0;
|
long expectedBalance_2 = 0;
|
||||||
|
|
||||||
Repository origRepository = new Repository();
|
RepositoryImpl origRepository = new RepositoryImpl();
|
||||||
Repository repository = origRepository.getTrack();
|
RepositoryImpl repository = origRepository.getTrack();
|
||||||
repository.startTracking();
|
repository.startTracking();
|
||||||
|
|
||||||
repository.createAccount(Hex.decode(addr));
|
repository.createAccount(Hex.decode(addr));
|
||||||
|
@ -336,8 +336,8 @@ public class RepositoryTest {
|
||||||
|
|
||||||
long expectedBalance = 55500;
|
long expectedBalance = 55500;
|
||||||
|
|
||||||
Repository origRepository = new Repository();
|
RepositoryImpl origRepository = new RepositoryImpl();
|
||||||
Repository repository = origRepository.getTrack();
|
RepositoryImpl repository = origRepository.getTrack();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
repository.createAccount(Hex.decode(addr_1));
|
repository.createAccount(Hex.decode(addr_1));
|
||||||
|
|
|
@ -15,7 +15,7 @@ import static org.junit.Assert.assertEquals;
|
||||||
public class UtilsTest {
|
public class UtilsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getValueShortString1() {
|
public void testGetValueShortString1() {
|
||||||
|
|
||||||
String expected = "123·(10^24)";
|
String expected = "123·(10^24)";
|
||||||
String result = Utils.getValueShortString(new BigInteger("123456789123445654363653463"));
|
String result = Utils.getValueShortString(new BigInteger("123456789123445654363653463"));
|
||||||
|
@ -24,7 +24,7 @@ public class UtilsTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getValueShortString2() {
|
public void testGetValueShortString2() {
|
||||||
|
|
||||||
String expected = "123·(10^3)";
|
String expected = "123·(10^3)";
|
||||||
String result = Utils.getValueShortString(new BigInteger("123456"));
|
String result = Utils.getValueShortString(new BigInteger("123456"));
|
||||||
|
@ -33,7 +33,7 @@ public class UtilsTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getValueShortString3() {
|
public void testGetValueShortString3() {
|
||||||
|
|
||||||
String expected = "1·(10^3)";
|
String expected = "1·(10^3)";
|
||||||
String result = Utils.getValueShortString(new BigInteger("1234"));
|
String result = Utils.getValueShortString(new BigInteger("1234"));
|
||||||
|
@ -42,7 +42,7 @@ public class UtilsTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getValueShortString4() {
|
public void testGetValueShortString4() {
|
||||||
|
|
||||||
String expected = "123·(10^0)";
|
String expected = "123·(10^0)";
|
||||||
String result = Utils.getValueShortString(new BigInteger("123"));
|
String result = Utils.getValueShortString(new BigInteger("123"));
|
||||||
|
@ -51,7 +51,7 @@ public class UtilsTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getValueShortString5() {
|
public void testGetValueShortString5() {
|
||||||
|
|
||||||
byte[] decimal = Hex.decode("3913517ebd3c0c65000000");
|
byte[] decimal = Hex.decode("3913517ebd3c0c65000000");
|
||||||
String expected = "69·(10^24)";
|
String expected = "69·(10^24)";
|
||||||
|
@ -59,4 +59,4 @@ public class UtilsTest {
|
||||||
|
|
||||||
assertEquals(expected, result);
|
assertEquals(expected, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,335 @@
|
||||||
|
package org.ethereum.vm;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.ethereum.util.ByteUtil;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class ProgramMemoryTest {
|
||||||
|
|
||||||
|
ProgramInvokeMockImpl pi = null;
|
||||||
|
Program program;
|
||||||
|
ByteBuffer memory;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void createProgram() {
|
||||||
|
program = new Program(ByteUtil.EMPTY_BYTE_ARRAY, pi);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetMemSize() {
|
||||||
|
ByteBuffer memory = ByteBuffer.allocate(64);
|
||||||
|
program.memory = memory;
|
||||||
|
assertEquals(64, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Ignore
|
||||||
|
public void testMemorySave() {
|
||||||
|
fail("Not yet implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Ignore
|
||||||
|
public void testMemoryLoad() {
|
||||||
|
fail("Not yet implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Ignore
|
||||||
|
public void testMemoryChunk() {
|
||||||
|
fail("Not yet implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemory1() {
|
||||||
|
|
||||||
|
memory = ByteBuffer.allocate(64);
|
||||||
|
int offset = 32;
|
||||||
|
int size = 32;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(64, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemory2() {
|
||||||
|
|
||||||
|
// memory.limit() > offset, == size
|
||||||
|
// memory.limit() < offset + size
|
||||||
|
memory = ByteBuffer.allocate(64);
|
||||||
|
int offset = 32;
|
||||||
|
int size = 64;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(96, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemory3() {
|
||||||
|
|
||||||
|
// memory.limit() > offset, > size
|
||||||
|
memory = ByteBuffer.allocate(64);
|
||||||
|
int offset = 0;
|
||||||
|
int size = 32;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(64, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemory4() {
|
||||||
|
|
||||||
|
memory = ByteBuffer.allocate(64);;
|
||||||
|
int offset = 0;
|
||||||
|
int size = 64;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(64, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemory5() {
|
||||||
|
|
||||||
|
memory = ByteBuffer.allocate(64);
|
||||||
|
int offset = 0;
|
||||||
|
int size = 0;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(64, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemory6() {
|
||||||
|
|
||||||
|
// memory.limit() == offset, > size
|
||||||
|
memory = ByteBuffer.allocate(64);
|
||||||
|
int offset = 64;
|
||||||
|
int size = 32;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(96, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemory7() {
|
||||||
|
|
||||||
|
// memory.limit() == offset - size
|
||||||
|
memory = ByteBuffer.allocate(64);
|
||||||
|
int offset = 96;
|
||||||
|
int size = 32;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(128, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemory8() {
|
||||||
|
|
||||||
|
memory = ByteBuffer.allocate(64);
|
||||||
|
int offset = 0;
|
||||||
|
int size = 96;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(96, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemory9() {
|
||||||
|
|
||||||
|
// memory.limit() < offset, > size
|
||||||
|
// memory.limit() < offset - size
|
||||||
|
memory = ByteBuffer.allocate(64);
|
||||||
|
int offset = 96;
|
||||||
|
int size = 0;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(96, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemory10() {
|
||||||
|
|
||||||
|
// memory = null, offset > size
|
||||||
|
int offset = 32;
|
||||||
|
int size = 0;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(32, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemory11() {
|
||||||
|
|
||||||
|
// memory = null, offset < size
|
||||||
|
int offset = 0;
|
||||||
|
int size = 32;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(32, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemory12() {
|
||||||
|
|
||||||
|
// memory.limit() < offset, < size
|
||||||
|
memory = ByteBuffer.allocate(32);
|
||||||
|
int offset = 64;
|
||||||
|
int size = 96;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(160, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemory13() {
|
||||||
|
|
||||||
|
// memory.limit() > offset, < size
|
||||||
|
memory = ByteBuffer.allocate(64);
|
||||||
|
int offset = 32;
|
||||||
|
int size = 128;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(160, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemory14() {
|
||||||
|
|
||||||
|
// memory.limit() < offset, == size
|
||||||
|
memory = ByteBuffer.allocate(64);
|
||||||
|
int offset = 96;
|
||||||
|
int size = 64;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(160, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemory15() {
|
||||||
|
|
||||||
|
// memory.limit() == offset, < size
|
||||||
|
memory = ByteBuffer.allocate(64);
|
||||||
|
int offset = 64;
|
||||||
|
int size = 96;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(160, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemory16() {
|
||||||
|
|
||||||
|
// memory.limit() == offset, == size
|
||||||
|
// memory.limit() > offset - size
|
||||||
|
memory = ByteBuffer.allocate(64);
|
||||||
|
int offset = 64;
|
||||||
|
int size = 64;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(128, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemory17() {
|
||||||
|
|
||||||
|
// memory.limit() > offset + size
|
||||||
|
memory = ByteBuffer.allocate(96);
|
||||||
|
int offset = 32;
|
||||||
|
int size = 32;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(96, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemoryUnrounded1() {
|
||||||
|
|
||||||
|
// memory unrounded
|
||||||
|
memory = ByteBuffer.allocate(16);
|
||||||
|
int offset = 64;
|
||||||
|
int size = 32;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(96, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemoryUnrounded2() {
|
||||||
|
|
||||||
|
// offset unrounded
|
||||||
|
memory = ByteBuffer.allocate(32);
|
||||||
|
int offset = 16;
|
||||||
|
int size = 32;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(64, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemoryUnrounded3() {
|
||||||
|
|
||||||
|
// size unrounded
|
||||||
|
memory = ByteBuffer.allocate(32);
|
||||||
|
int offset = 64;
|
||||||
|
int size = 16;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(96, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemoryUnrounded4() {
|
||||||
|
|
||||||
|
// memory + offset unrounded
|
||||||
|
memory = ByteBuffer.allocate(16);
|
||||||
|
int offset = 16;
|
||||||
|
int size = 32;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(64 , program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemoryUnrounded5() {
|
||||||
|
|
||||||
|
// memory + size unrounded
|
||||||
|
memory = ByteBuffer.allocate(16);
|
||||||
|
int offset = 32;
|
||||||
|
int size = 16;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(64, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemoryUnrounded6() {
|
||||||
|
|
||||||
|
// offset + size unrounded
|
||||||
|
memory = ByteBuffer.allocate(32);
|
||||||
|
int offset = 16;
|
||||||
|
int size = 16;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(32, program.getMemSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllocateMemoryUnrounded7() {
|
||||||
|
|
||||||
|
// memory + offset + size unrounded
|
||||||
|
memory = ByteBuffer.allocate(16);
|
||||||
|
int offset = 16;
|
||||||
|
int size = 16;
|
||||||
|
program.memory = memory;
|
||||||
|
program.allocateMemory(offset, size);
|
||||||
|
assertEquals(32,program.getMemSize());
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ package org.ethereum.vm;
|
||||||
|
|
||||||
import org.ethereum.core.AccountState;
|
import org.ethereum.core.AccountState;
|
||||||
import org.ethereum.crypto.HashUtil;
|
import org.ethereum.crypto.HashUtil;
|
||||||
import org.ethereum.db.Repository;
|
import org.ethereum.db.RepositoryImpl;
|
||||||
import org.junit.FixMethodOrder;
|
import org.junit.FixMethodOrder;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -59,7 +59,7 @@ public class VMComplexTest {
|
||||||
|
|
||||||
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
||||||
pi.setOwnerAddress("77045e71a7a2c50903d88e564cd72fab11e82051");
|
pi.setOwnerAddress("77045e71a7a2c50903d88e564cd72fab11e82051");
|
||||||
Repository repository = pi.getRepository();
|
RepositoryImpl repository = pi.getRepository();
|
||||||
|
|
||||||
repository.createAccount(callerAddrB);
|
repository.createAccount(callerAddrB);
|
||||||
repository.addBalance(callerAddrB, new BigInteger("100000000000000000000"));
|
repository.addBalance(callerAddrB, new BigInteger("100000000000000000000"));
|
||||||
|
@ -134,7 +134,7 @@ public class VMComplexTest {
|
||||||
|
|
||||||
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
||||||
pi.setOwnerAddress(contractB_addr);
|
pi.setOwnerAddress(contractB_addr);
|
||||||
Repository repository = pi.getRepository();
|
RepositoryImpl repository = pi.getRepository();
|
||||||
|
|
||||||
byte[] contractB_addr_bytes = Hex.decode(contractB_addr);
|
byte[] contractB_addr_bytes = Hex.decode(contractB_addr);
|
||||||
byte[] codeB = Hex.decode(code_b);
|
byte[] codeB = Hex.decode(code_b);
|
||||||
|
@ -234,7 +234,7 @@ public class VMComplexTest {
|
||||||
|
|
||||||
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
||||||
pi.setOwnerAddress(contractB_addr);
|
pi.setOwnerAddress(contractB_addr);
|
||||||
Repository repository = pi.getRepository();
|
RepositoryImpl repository = pi.getRepository();
|
||||||
repository.createAccount(contractA_addr_bytes);
|
repository.createAccount(contractA_addr_bytes);
|
||||||
repository.saveCode(contractA_addr_bytes, codeA);
|
repository.saveCode(contractA_addr_bytes, codeA);
|
||||||
|
|
||||||
|
@ -315,7 +315,7 @@ public class VMComplexTest {
|
||||||
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
||||||
pi.setOwnerAddress(contractA_addr);
|
pi.setOwnerAddress(contractA_addr);
|
||||||
|
|
||||||
Repository repository = pi.getRepository();
|
RepositoryImpl repository = pi.getRepository();
|
||||||
|
|
||||||
byte[] caller_addr_bytes = Hex.decode(callerAddr);
|
byte[] caller_addr_bytes = Hex.decode(callerAddr);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package org.ethereum.vm;
|
package org.ethereum.vm;
|
||||||
|
|
||||||
import org.ethereum.db.Repository;
|
import org.ethereum.db.RepositoryImpl;
|
||||||
import org.ethereum.vm.Program.OutOfGasException;
|
import org.ethereum.vm.Program.OutOfGasException;
|
||||||
import org.junit.FixMethodOrder;
|
import org.junit.FixMethodOrder;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -1540,7 +1540,7 @@ public class VMTest {
|
||||||
vm.step(program);
|
vm.step(program);
|
||||||
vm.step(program);
|
vm.step(program);
|
||||||
|
|
||||||
Repository repository = program.result.getRepository();
|
RepositoryImpl repository = program.result.getRepository();
|
||||||
DataWord key = new DataWord(Hex.decode(s_expected_key));
|
DataWord key = new DataWord(Hex.decode(s_expected_key));
|
||||||
DataWord val = repository.getStorageValue(invoke.getOwnerAddress().getNoLeadZeroesData(), key);
|
DataWord val = repository.getStorageValue(invoke.getOwnerAddress().getNoLeadZeroesData(), key);
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ package org.ethereum.gui;
|
||||||
|
|
||||||
import org.ethereum.core.Block;
|
import org.ethereum.core.Block;
|
||||||
import org.ethereum.core.Transaction;
|
import org.ethereum.core.Transaction;
|
||||||
import org.ethereum.db.Repository;
|
import org.ethereum.db.RepositoryImpl;
|
||||||
import org.ethereum.manager.WorldManager;
|
import org.ethereum.manager.WorldManager;
|
||||||
import org.ethereum.vm.*;
|
import org.ethereum.vm.*;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
@ -49,7 +49,7 @@ public class ProgramPlayDialog extends JPanel implements ActionListener,
|
||||||
outputList = new ArrayList<String>();
|
outputList = new ArrayList<String>();
|
||||||
VM vm = new VM();
|
VM vm = new VM();
|
||||||
|
|
||||||
Repository tractRepository = WorldManager.getInstance().getRepository().getTrack();
|
RepositoryImpl tractRepository = WorldManager.getInstance().getRepository().getTrack();
|
||||||
|
|
||||||
Program program = new Program(code ,
|
Program program = new Program(code ,
|
||||||
ProgramInvokeFactory.createProgramInvoke(tx, lastBlock, tractRepository));
|
ProgramInvokeFactory.createProgramInvoke(tx, lastBlock, tractRepository));
|
||||||
|
|
Loading…
Reference in New Issue