mirror of
https://github.com/status-im/ethereumj-personal.git
synced 2025-01-29 21:25:30 +00:00
New Repositroy management:
+ Included and refactored all the repository usage + VMTest all pass + VMComplex test except 4 all pass - The rootState of the blcok need sollution - The contract create contract test VMComplexTest 4 need recheck
This commit is contained in:
parent
9d650350f0
commit
415f87c727
@ -71,7 +71,11 @@ public class Block {
|
||||
difficulty, number, minGasPrice, gasLimit, gasUsed,
|
||||
timestamp, extraData, nonce);
|
||||
this.txsState = new Trie(null);
|
||||
this.header.setStateRoot(WorldManager.instance.worldState.getRootHash());
|
||||
|
||||
// TODO: REFACTOR REPOSITORY TO GET ROOT HASH FOR HERE
|
||||
// TODO: REFACTOR REPOSITORY TO GET ROOT HASH FOR HERE
|
||||
// TODO: REFACTOR REPOSITORY TO GET ROOT HASH FOR HERE
|
||||
this.header.setStateRoot(null);
|
||||
this.header.setTxTrieRoot(txsState.getRootHash());
|
||||
this.transactionsList = transactionsList;
|
||||
this.uncleList = uncleList;
|
||||
@ -197,7 +201,7 @@ public class Block {
|
||||
public List<Transaction> getTransactionsList() {
|
||||
if (!parsed) parseRLP();
|
||||
if (transactionsList == null) {
|
||||
this.transactionsList = new ArrayList<Transaction>();
|
||||
this.transactionsList = new ArrayList<>();
|
||||
}
|
||||
return transactionsList;
|
||||
}
|
||||
@ -205,7 +209,7 @@ public class Block {
|
||||
public List<TransactionReceipt> getTxReceiptList() {
|
||||
if (!parsed) parseRLP();
|
||||
if (transactionsList == null) {
|
||||
this.txReceiptList = new ArrayList<TransactionReceipt>();
|
||||
this.txReceiptList = new ArrayList<>();
|
||||
}
|
||||
return txReceiptList;
|
||||
}
|
||||
@ -213,7 +217,7 @@ public class Block {
|
||||
public List<Block> getUncleList() {
|
||||
if (!parsed) parseRLP();
|
||||
if (uncleList == null) {
|
||||
this.uncleList = new ArrayList<Block>();
|
||||
this.uncleList = new ArrayList<>();
|
||||
}
|
||||
return uncleList;
|
||||
}
|
||||
@ -299,14 +303,6 @@ public class Block {
|
||||
// this.allAccountsState.update();
|
||||
}
|
||||
|
||||
public byte[] updateState(byte[] key, byte[] value) {
|
||||
|
||||
WorldManager.instance.worldState.update(key, value);
|
||||
byte[] stateRoot = WorldManager.instance.worldState.getRootHash();
|
||||
this.header.setStateRoot(stateRoot);
|
||||
return stateRoot;
|
||||
}
|
||||
|
||||
/**
|
||||
* This mechanism enforces a homeostasis in terms of the time between blocks;
|
||||
* a smaller period between the last two blocks results in an increase in the
|
||||
@ -320,7 +316,6 @@ public class Block {
|
||||
if(!this.isGenesis()) {
|
||||
// verify difficulty meets requirements
|
||||
isValid = this.getDifficulty() == this.calcDifficulty();
|
||||
// verify nonce meest difficulty requirements
|
||||
isValid = this.validateNonce();
|
||||
// verify gasLimit meets requirements
|
||||
isValid = this.getGasLimit() == this.calcGasLimit();
|
||||
@ -367,9 +362,6 @@ public class Block {
|
||||
/**
|
||||
* Verify that block is valid for its difficulty
|
||||
*
|
||||
* @param block
|
||||
* @param difficulty
|
||||
* @param testNonce
|
||||
* @return
|
||||
*/
|
||||
public boolean validateNonce() {
|
||||
|
@ -1,106 +0,0 @@
|
||||
package org.ethereum.core;
|
||||
|
||||
import org.ethereum.util.RLP;
|
||||
import org.ethereum.util.RLPElement;
|
||||
import org.ethereum.util.RLPItem;
|
||||
import org.ethereum.util.RLPList;
|
||||
import org.ethereum.vm.DataWord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
*
|
||||
* @author: Roman Mandeleil
|
||||
* Created on: 09/06/2014 15:31
|
||||
*/
|
||||
|
||||
public class ContractDetails {
|
||||
|
||||
private byte[] rlpEncoded;
|
||||
|
||||
List<DataWord> storageKeys;
|
||||
List<DataWord> storageValues;
|
||||
|
||||
public ContractDetails(byte[] rlpEncoded) {
|
||||
|
||||
RLPList data = RLP.decode2(rlpEncoded);
|
||||
RLPList rlpList = (RLPList)data.get(0);
|
||||
|
||||
RLPList keys = (RLPList)rlpList.get(0);
|
||||
RLPList values = (RLPList)rlpList.get(1);
|
||||
|
||||
if (keys.size() > 0){
|
||||
storageKeys = new ArrayList<>();
|
||||
storageValues = new ArrayList<>();
|
||||
}
|
||||
|
||||
for (int i = 0; i < keys.size(); ++i){
|
||||
|
||||
RLPItem rlpItem = (RLPItem)keys.get(i);
|
||||
storageKeys.add(new DataWord(rlpItem.getRLPData()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < values.size(); ++i){
|
||||
RLPItem rlpItem = (RLPItem)values.get(i);
|
||||
storageValues.add(new DataWord(rlpItem.getRLPData()));
|
||||
}
|
||||
}
|
||||
|
||||
public ContractDetails(Map<DataWord, DataWord> storage) {
|
||||
|
||||
storageKeys = new ArrayList<DataWord>();
|
||||
storageValues = new ArrayList<DataWord>();
|
||||
|
||||
for(DataWord key : storage.keySet()){
|
||||
|
||||
DataWord value = storage.get(key);
|
||||
|
||||
storageKeys.add(key);
|
||||
storageValues.add(value);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getEncoded() {
|
||||
if(rlpEncoded == null) {
|
||||
|
||||
byte[][] keys = new byte[storageKeys.size()][];
|
||||
byte[][] values = new byte[storageValues.size()][];
|
||||
|
||||
int i = 0;
|
||||
for (DataWord key : storageKeys){
|
||||
keys[i] = RLP.encodeElement( key.getData());
|
||||
++i;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for (DataWord value : storageValues){
|
||||
values[i] = RLP.encodeElement( value.getData() );
|
||||
++i;
|
||||
}
|
||||
|
||||
byte[] rlpKeysList = RLP.encodeList(keys);
|
||||
byte[] rlpValuesList = RLP.encodeList(values);
|
||||
|
||||
this.rlpEncoded = RLP.encodeList(rlpKeysList, rlpValuesList);
|
||||
}
|
||||
return rlpEncoded;
|
||||
}
|
||||
|
||||
|
||||
public Map<DataWord, DataWord> getStorage(){
|
||||
|
||||
Map<DataWord, DataWord> storage = new HashMap<>();
|
||||
|
||||
for (int i = 0;
|
||||
storageKeys != null &&
|
||||
i < storageKeys.size(); ++i){
|
||||
storage.put(storageKeys.get(i), storageValues.get(i));
|
||||
}
|
||||
|
||||
return storage;
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package org.ethereum.core;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.ethereum.crypto.HashUtil;
|
||||
import org.ethereum.manager.WorldManager;
|
||||
import org.ethereum.util.RLP;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -69,8 +70,9 @@ public class Genesis extends Block {
|
||||
|
||||
// Premine state
|
||||
for (String address : premine) {
|
||||
this.updateState(Hex.decode(address), acct.getEncoded());
|
||||
}
|
||||
WorldManager.instance.repository.createAccount(Hex.decode(address));
|
||||
WorldManager.instance.repository.addBalance(Hex.decode(address), BigInteger.valueOf(2).pow(200) );
|
||||
}
|
||||
logger.info("Genesis-hash: " + Hex.toHexString(this.getHash()));
|
||||
logger.info("Genesis-stateRoot: " + Hex.toHexString(this.getStateRoot()));
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import java.util.*;
|
||||
* Created on: 24/06/2014 00:12
|
||||
*/
|
||||
|
||||
public class NewContractDetails {
|
||||
public class ContractDetails {
|
||||
|
||||
private byte[] rlpEncoded;
|
||||
|
||||
@ -29,18 +29,27 @@ public class NewContractDetails {
|
||||
Trie storageTrie = new Trie(null);
|
||||
|
||||
|
||||
public NewContractDetails(){}
|
||||
public NewContractDetails(byte[] rlpCode) {
|
||||
public ContractDetails(){}
|
||||
public ContractDetails(byte[] rlpCode) {
|
||||
decode(rlpCode);
|
||||
}
|
||||
|
||||
public NewContractDetails(Map<DataWord, DataWord> storage, byte[] code) {}
|
||||
public ContractDetails(Map<DataWord, DataWord> storage, byte[] code) {}
|
||||
|
||||
public void put(DataWord key, DataWord value){
|
||||
|
||||
storageTrie.update(key.getData(), value.getData());
|
||||
|
||||
int index = storageKeys.indexOf(key);
|
||||
|
||||
if (index != -1){
|
||||
storageKeys.remove(index);
|
||||
storageValues.remove(index);
|
||||
}
|
||||
|
||||
storageKeys.add(key);
|
||||
storageValues.add(value);
|
||||
|
||||
this.rlpEncoded = null;
|
||||
}
|
||||
|
||||
@ -145,7 +154,7 @@ public class NewContractDetails {
|
||||
|
||||
public Map<DataWord, DataWord> getStorage(){
|
||||
|
||||
Map<DataWord, DataWord> storage = Collections.unmodifiableMap(new HashMap<DataWord, DataWord>());
|
||||
Map<DataWord, DataWord> storage = new HashMap<DataWord, DataWord>();
|
||||
|
||||
for (int i = 0;
|
||||
storageKeys != null &&
|
||||
@ -153,7 +162,7 @@ public class NewContractDetails {
|
||||
storage.put(storageKeys.get(i), storageValues.get(i));
|
||||
}
|
||||
|
||||
return storage;
|
||||
return Collections.unmodifiableMap(storage);
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
package org.ethereum.db;
|
||||
|
||||
import org.ethereum.core.AccountState;
|
||||
import org.ethereum.core.ContractDetails;
|
||||
import org.ethereum.crypto.HashUtil;
|
||||
import org.ethereum.trie.TrackTrie;
|
||||
import org.ethereum.trie.Trie;
|
||||
@ -98,7 +97,7 @@ public class Repository {
|
||||
accountStateDB.update(addr, state.getEncoded());
|
||||
|
||||
// 2. Save ContractDetails
|
||||
NewContractDetails details = new NewContractDetails();
|
||||
ContractDetails details = new ContractDetails();
|
||||
contractDetailsDB.put(addr, details.getEncoded());
|
||||
|
||||
return state;
|
||||
@ -119,7 +118,7 @@ public class Repository {
|
||||
return state;
|
||||
}
|
||||
|
||||
public NewContractDetails getContractDetails(byte[] addr){
|
||||
public ContractDetails getContractDetails(byte[] addr){
|
||||
|
||||
byte[] accountDetailsRLP = contractDetailsDB.get(addr);
|
||||
|
||||
@ -130,7 +129,7 @@ public class Repository {
|
||||
return null;
|
||||
}
|
||||
|
||||
NewContractDetails details = new NewContractDetails(accountDetailsRLP);
|
||||
ContractDetails details = new ContractDetails(accountDetailsRLP);
|
||||
return details;
|
||||
}
|
||||
|
||||
@ -186,7 +185,7 @@ public class Repository {
|
||||
|
||||
if (address == null || key == null) return;
|
||||
AccountState state = getAccountState(address);
|
||||
NewContractDetails details = getContractDetails(address);
|
||||
ContractDetails details = getContractDetails(address);
|
||||
|
||||
if (state == null || details == null) return;
|
||||
details.put(key, value);
|
||||
@ -211,7 +210,7 @@ public class Repository {
|
||||
AccountState state = getAccountState(address);
|
||||
if (state == null) return null;
|
||||
|
||||
NewContractDetails details = getContractDetails(address);
|
||||
ContractDetails details = getContractDetails(address);
|
||||
DataWord value = details.get(key);
|
||||
|
||||
return value;
|
||||
@ -219,7 +218,7 @@ public class Repository {
|
||||
|
||||
public byte[] getCode(byte[] address){
|
||||
|
||||
NewContractDetails details = getContractDetails(address);
|
||||
ContractDetails details = getContractDetails(address);
|
||||
if (details == null) return null;
|
||||
|
||||
return details.getCode();
|
||||
@ -232,7 +231,7 @@ public class Repository {
|
||||
AccountState state = getAccountState(address);
|
||||
if (state == null) return;
|
||||
|
||||
NewContractDetails details = getContractDetails(address);
|
||||
ContractDetails details = getContractDetails(address);
|
||||
details.setCode(code);
|
||||
|
||||
byte[] codeHash = HashUtil.sha3(code);
|
||||
|
@ -1,15 +1,13 @@
|
||||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.core.Account;
|
||||
import org.ethereum.core.AccountState;
|
||||
import org.ethereum.core.ContractDetails;
|
||||
import org.ethereum.core.Transaction;
|
||||
import org.ethereum.db.ContractDetails;
|
||||
import org.ethereum.manager.MainData;
|
||||
import org.ethereum.manager.WorldManager;
|
||||
import org.ethereum.net.client.ClientPeer;
|
||||
import org.ethereum.util.ByteUtil;
|
||||
import org.ethereum.util.Utils;
|
||||
import org.ethereum.vm.DataWord;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.spongycastle.util.BigIntegers;
|
||||
@ -27,7 +25,6 @@ import java.awt.event.*;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URL;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -229,35 +226,8 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
|
||||
}
|
||||
|
||||
byte[] contractAddress = Hex.decode( contractAddr );
|
||||
byte[] contractStateB = WorldManager.instance.worldState.get(contractAddress);
|
||||
if (contractStateB == null || contractStateB.length == 0){
|
||||
return;
|
||||
}
|
||||
|
||||
AccountState contractState = new AccountState(contractStateB);
|
||||
final byte[] programCode = WorldManager.instance.chainDB.get(contractState.getCodeHash());
|
||||
if (programCode == null || programCode.length == 0){
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] contractDetailsB =
|
||||
WorldManager.instance.detaildDB.get(contractAddress);
|
||||
|
||||
ContractDetails contractDetails = null;
|
||||
final Map storageMap = new HashMap();
|
||||
|
||||
if (contractDetailsB != null){
|
||||
|
||||
contractDetails = new ContractDetails(contractDetailsB);
|
||||
Map<DataWord, DataWord> tmpStorage = contractDetails.getStorage();
|
||||
if (tmpStorage != null){
|
||||
for (DataWord key : tmpStorage.keySet()){
|
||||
String keyToSave = Hex.toHexString (key.getNoLeadZeroesData());
|
||||
String valueToSave = Hex.toHexString (tmpStorage.get(key).getNoLeadZeroesData());
|
||||
storageMap.put(keyToSave, valueToSave);
|
||||
}
|
||||
}
|
||||
}
|
||||
final byte[] programCode = WorldManager.instance.repository.getCode(contractAddress);
|
||||
final Map storageMap = WorldManager.instance.repository.getContractDetails(contractAddress).getStorage();
|
||||
|
||||
contractDataInput.setBounds(70, 80, 350, 145);
|
||||
contractDataInput.setViewportView(msgDataTA);
|
||||
@ -335,31 +305,23 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog{
|
||||
|
||||
private void playContractCall() {
|
||||
|
||||
byte[] contractAddress = Hex.decode( contractAddrInput.getText());
|
||||
byte[] contractStateB = WorldManager.instance.worldState.get(contractAddress);
|
||||
if (contractStateB == null || contractStateB.length == 0){
|
||||
byte[] contractAddress = Hex.decode(contractAddrInput.getText());
|
||||
ContractDetails contractDetails = WorldManager.instance.repository.getContractDetails(contractAddress);
|
||||
if (contractDetails == null){
|
||||
alertStatusMsg("No contract for that address");
|
||||
return;
|
||||
}
|
||||
|
||||
AccountState contractState = new AccountState(contractStateB);
|
||||
byte[] programCode = WorldManager.instance.chainDB.get(contractState.getCodeHash());
|
||||
byte[] programCode = WorldManager.instance.repository.getCode(contractAddress);
|
||||
if (programCode == null || programCode.length == 0){
|
||||
alertStatusMsg("Such account exist but no code in the db");
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] contractDetailsB =
|
||||
WorldManager.instance.detaildDB.get(contractAddress);
|
||||
|
||||
ContractDetails contractDetails = null;
|
||||
if (contractDetailsB != null && contractDetailsB.length > 0)
|
||||
contractDetails = new ContractDetails(contractDetailsB);
|
||||
|
||||
Transaction tx = createTransaction();
|
||||
if (tx == null) return;
|
||||
|
||||
ProgramPlayDialog.createAndShowGUI(programCode, tx, WorldManager.instance.getBlockChain().getLastBlock(), contractDetails);
|
||||
ProgramPlayDialog.createAndShowGUI(programCode, tx, WorldManager.instance.getBlockChain().getLastBlock());
|
||||
}
|
||||
|
||||
protected JRootPane createRootPane() {
|
||||
|
@ -109,7 +109,7 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog {
|
||||
contractAddrInput.setText(Hex.toHexString(tx.getContractAddress()));
|
||||
|
||||
ProgramPlayDialog.createAndShowGUI(tx.getData(), tx,
|
||||
WorldManager.instance.getBlockChain().getLastBlock(), null);
|
||||
WorldManager.instance.getBlockChain().getLastBlock());
|
||||
}}
|
||||
);
|
||||
|
||||
|
@ -1,14 +1,11 @@
|
||||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.core.Block;
|
||||
import org.ethereum.core.ContractDetails;
|
||||
import org.ethereum.core.Transaction;
|
||||
import org.ethereum.db.TrackDatabase;
|
||||
import org.ethereum.db.Repository;
|
||||
import org.ethereum.manager.WorldManager;
|
||||
import org.ethereum.serpent.SerpentCompiler;
|
||||
import org.ethereum.trie.TrackTrie;
|
||||
import org.ethereum.vm.*;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
@ -16,7 +13,7 @@ import javax.swing.event.ChangeListener;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -52,29 +49,23 @@ public class ProgramPlayDialog extends JPanel implements ActionListener,
|
||||
}
|
||||
|
||||
|
||||
public ProgramPlayDialog(byte[] code, Transaction tx, Block lastBlock, ContractDetails contractDetails) {
|
||||
public ProgramPlayDialog(byte[] code, Transaction tx, Block lastBlock) {
|
||||
|
||||
this.tx = tx;
|
||||
|
||||
outputList = new ArrayList<String>();
|
||||
VM vm = new VM();
|
||||
|
||||
TrackDatabase trackDetailDB = new TrackDatabase( WorldManager.instance.detaildDB );
|
||||
TrackDatabase trackChainDb = new TrackDatabase( WorldManager.instance.chainDB);
|
||||
TrackTrie trackStateDB = new TrackTrie(WorldManager.instance.worldState );
|
||||
Repository tractRepository = WorldManager.instance.repository.getTrack();
|
||||
|
||||
Program program = new Program(code ,
|
||||
ProgramInvokeFactory.createProgramInvoke(tx, lastBlock, contractDetails,
|
||||
trackDetailDB, trackChainDb, trackStateDB));
|
||||
ProgramInvokeFactory.createProgramInvoke(tx, lastBlock, tractRepository));
|
||||
|
||||
program.addListener(this);
|
||||
program.fullTrace();
|
||||
vm.play(program);
|
||||
|
||||
trackDetailDB.rollbackTrack();
|
||||
trackChainDb.rollbackTrack();
|
||||
trackStateDB.rollbackTrack();
|
||||
|
||||
tractRepository.rollback();
|
||||
|
||||
doGUI();
|
||||
}
|
||||
@ -155,11 +146,11 @@ public class ProgramPlayDialog extends JPanel implements ActionListener,
|
||||
* this method should be invoked from the
|
||||
* event-dispatching thread.
|
||||
*/
|
||||
public static void createAndShowGUI(byte[] runCode, Transaction tx, Block lastBlock, ContractDetails details) {
|
||||
public static void createAndShowGUI(byte[] runCode, Transaction tx, Block lastBlock) {
|
||||
|
||||
ProgramPlayDialog ppd;
|
||||
if (tx != null)
|
||||
ppd = new ProgramPlayDialog(runCode, tx, lastBlock, details);
|
||||
ppd = new ProgramPlayDialog(runCode, tx, lastBlock);
|
||||
else{
|
||||
ppd = new ProgramPlayDialog(runCode);
|
||||
}
|
||||
@ -204,7 +195,7 @@ public class ProgramPlayDialog extends JPanel implements ActionListener,
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
createAndShowGUI(code, null, null, null);
|
||||
createAndShowGUI(code, null, null);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -4,6 +4,7 @@ import org.ethereum.core.*;
|
||||
import org.ethereum.crypto.ECKey;
|
||||
import org.ethereum.crypto.HashUtil;
|
||||
import org.ethereum.db.DatabaseImpl;
|
||||
import org.ethereum.db.Repository;
|
||||
import org.ethereum.db.TrackDatabase;
|
||||
import org.ethereum.trie.TrackTrie;
|
||||
import org.ethereum.trie.Trie;
|
||||
@ -43,10 +44,8 @@ public class WorldManager {
|
||||
Collections.synchronizedMap(new HashMap<String, Transaction>());
|
||||
|
||||
public DatabaseImpl chainDB = new DatabaseImpl("blockchain");
|
||||
public DatabaseImpl stateDB = new DatabaseImpl("state");
|
||||
public DatabaseImpl detaildDB = new DatabaseImpl("details");
|
||||
|
||||
public Trie worldState = new Trie(stateDB.getDb());
|
||||
public Repository repository = new Repository();
|
||||
|
||||
public static WorldManager instance = new WorldManager();
|
||||
public WorldManager() {
|
||||
@ -84,19 +83,21 @@ public class WorldManager {
|
||||
|
||||
// 1. VALIDATE THE NONCE
|
||||
byte[] senderAddress = tx.getSender();
|
||||
byte[] stateData = worldState.get(senderAddress);
|
||||
|
||||
if (stateData == null || stateData.length == 0) {
|
||||
AccountState senderAccount = repository.getAccountState(senderAddress);
|
||||
|
||||
if (senderAccount == null) {
|
||||
if (stateLogger.isWarnEnabled())
|
||||
stateLogger.warn("No such address: {}", Hex.toHexString(senderAddress));
|
||||
return;
|
||||
}
|
||||
|
||||
AccountState senderState = new AccountState(stateData);
|
||||
if (senderState.getNonce().compareTo(new BigInteger(tx.getNonce())) != 0) {
|
||||
|
||||
BigInteger nonce = repository.getNonce(senderAddress);
|
||||
if (nonce.compareTo(new BigInteger(tx.getNonce())) != 0) {
|
||||
if (stateLogger.isWarnEnabled())
|
||||
stateLogger.warn("Invalid nonce account.nonce={} tx.nonce={}",
|
||||
senderState.getNonce(), new BigInteger(tx.getNonce()));
|
||||
nonce.longValue(), new BigInteger(tx.getNonce()));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -104,8 +105,9 @@ public class WorldManager {
|
||||
// (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION)
|
||||
|
||||
// first of all debit the gas from the issuer
|
||||
AccountState receiverState = null;
|
||||
BigInteger gasDebit = tx.getTotalGasValueDebit();
|
||||
gasDebit = gasDebit.multiply(new BigInteger(tx.getGasPrice()));
|
||||
|
||||
byte[] contractAddress;
|
||||
|
||||
// Contract creation or existing Contract call
|
||||
@ -113,32 +115,27 @@ public class WorldManager {
|
||||
|
||||
// credit the receiver
|
||||
contractAddress = tx.getContractAddress();
|
||||
receiverState = new AccountState();
|
||||
worldState.update(contractAddress, receiverState.getEncoded());
|
||||
repository.createAccount(contractAddress);
|
||||
stateLogger.info("New contract created address={}",
|
||||
Hex.toHexString(contractAddress));
|
||||
} else {
|
||||
|
||||
contractAddress = tx.getReceiveAddress();
|
||||
byte[] accountData = this.worldState.get(tx.getReceiveAddress());
|
||||
if (accountData.length == 0){
|
||||
receiverState = new AccountState();
|
||||
AccountState receiverState = repository.getAccountState(tx.getReceiveAddress());
|
||||
|
||||
if (receiverState == null){
|
||||
repository.createAccount(tx.getReceiveAddress());
|
||||
if (stateLogger.isInfoEnabled())
|
||||
stateLogger.info("New account created address={}",
|
||||
Hex.toHexString(tx.getReceiveAddress()));
|
||||
} else {
|
||||
receiverState = new AccountState(accountData);
|
||||
if (stateLogger.isInfoEnabled())
|
||||
stateLogger.info("Account found address={}",
|
||||
Hex.toHexString(tx.getReceiveAddress()));
|
||||
}
|
||||
}
|
||||
|
||||
// 2.2 UPDATE THE NONCE
|
||||
// (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION)
|
||||
if (senderState.getBalance().compareTo(BigInteger.ZERO) == 1) {
|
||||
senderState.incrementNonce();
|
||||
worldState.update(tx.getSender(), senderState.getEncoded());
|
||||
BigInteger balance = repository.getBalance(senderAddress);
|
||||
if (balance.compareTo(BigInteger.ZERO) == 1) {
|
||||
repository.increaseNonce(senderAddress);
|
||||
|
||||
if(stateLogger.isInfoEnabled())
|
||||
stateLogger.info("Before contract execution the sender address debit with gas total cost, " +
|
||||
@ -153,34 +150,30 @@ public class WorldManager {
|
||||
// can be validate using GAS op
|
||||
if (gasDebit.signum() == 1){
|
||||
|
||||
if (senderState.getBalance().subtract(gasDebit).signum() == -1){
|
||||
if (balance.compareTo( gasDebit ) == -1){
|
||||
logger.info("No gas to start the execution: sender={}" , Hex.toHexString(tx.getSender()));
|
||||
return;
|
||||
}
|
||||
senderState.addToBalance(gasDebit.negate());
|
||||
worldState.update(senderAddress, senderState.getEncoded());
|
||||
repository.addBalance(senderAddress, gasDebit.negate());
|
||||
}
|
||||
|
||||
// 3. START TRACKING FOR REVERT CHANGES OPTION !!!
|
||||
TrackDatabase trackDetailDB = new TrackDatabase( WorldManager.instance.detaildDB );
|
||||
TrackDatabase trackChainDb = new TrackDatabase( WorldManager.instance.chainDB);
|
||||
TrackTrie trackStateDB = new TrackTrie(WorldManager.instance.worldState );
|
||||
|
||||
trackDetailDB.startTrack();
|
||||
trackChainDb.startTrack();
|
||||
trackStateDB.startTrack();
|
||||
Repository trackRepository = repository.getTrack();
|
||||
trackRepository.startTracking();
|
||||
|
||||
try {
|
||||
|
||||
// 4. THE SIMPLE VALUE/BALANCE CHANGE
|
||||
if(tx.getValue() != null) {
|
||||
|
||||
if (senderState.getBalance().subtract(new BigInteger(1, tx.getValue())).signum() >= 0){
|
||||
receiverState.addToBalance(new BigInteger(1, tx.getValue()));
|
||||
senderState.addToBalance(new BigInteger(1, tx.getValue()).negate());
|
||||
BigInteger senderBalance = repository.getBalance(senderAddress);
|
||||
BigInteger contractBalance = repository.getBalance(contractAddress);
|
||||
|
||||
trackStateDB.update(senderAddress, senderState.getEncoded());
|
||||
trackStateDB.update(contractAddress, receiverState.getEncoded());
|
||||
|
||||
if ( senderBalance.compareTo(new BigInteger(1, tx.getValue())) >= 0){
|
||||
|
||||
repository.addBalance(contractAddress, new BigInteger(1, tx.getValue()));
|
||||
repository.addBalance(senderAddress, new BigInteger(1, tx.getValue()).negate());
|
||||
|
||||
if (stateLogger.isInfoEnabled())
|
||||
stateLogger.info("Update value balance \n " +
|
||||
@ -200,7 +193,7 @@ public class WorldManager {
|
||||
blockChain.getLastBlock();
|
||||
|
||||
ProgramInvoke programInvoke =
|
||||
ProgramInvokeFactory.createProgramInvoke(tx, lastBlock, null, trackDetailDB, trackChainDb, trackStateDB);
|
||||
ProgramInvokeFactory.createProgramInvoke(tx, lastBlock, trackRepository);
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info("running the init for contract: addres={}" ,
|
||||
@ -211,14 +204,12 @@ public class WorldManager {
|
||||
Program program = new Program(initCode, programInvoke);
|
||||
vm.play(program);
|
||||
ProgramResult result = program.getResult();
|
||||
applyProgramResult(result, gasDebit, senderState, receiverState, senderAddress, tx.getContractAddress());
|
||||
applyProgramResult(result, gasDebit, trackRepository, senderAddress, tx.getContractAddress());
|
||||
|
||||
} else {
|
||||
|
||||
if (receiverState.getCodeHash() != HashUtil.EMPTY_DATA_HASH){
|
||||
|
||||
byte[] programCode = chainDB.get(receiverState.getCodeHash());
|
||||
if (programCode != null && programCode.length != 0){
|
||||
byte[] programCode = trackRepository.getCode(tx.getReceiveAddress());
|
||||
if (programCode != null){
|
||||
|
||||
Block lastBlock =
|
||||
blockChain.getLastBlock();
|
||||
@ -227,36 +218,24 @@ public class WorldManager {
|
||||
logger.info("calling for existing contract: addres={}" , Hex.toHexString(tx.getReceiveAddress()));
|
||||
|
||||
|
||||
// FETCH THE SAVED STORAGE
|
||||
ContractDetails details = null;
|
||||
byte[] detailsRLPData = detaildDB.get(tx.getReceiveAddress());
|
||||
if (detailsRLPData.length > 0)
|
||||
details = new ContractDetails(detailsRLPData);
|
||||
|
||||
ProgramInvoke programInvoke =
|
||||
ProgramInvokeFactory.createProgramInvoke(tx, lastBlock, details, trackDetailDB, trackChainDb, trackStateDB);
|
||||
ProgramInvokeFactory.createProgramInvoke(tx, lastBlock, trackRepository);
|
||||
|
||||
VM vm = new VM();
|
||||
Program program = new Program(programCode, programInvoke);
|
||||
vm.play(program);
|
||||
|
||||
ProgramResult result = program.getResult();
|
||||
applyProgramResult(result, gasDebit, senderState, receiverState, senderAddress, tx.getReceiveAddress());
|
||||
}
|
||||
applyProgramResult(result, gasDebit, trackRepository, senderAddress, tx.getReceiveAddress());
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
|
||||
trackDetailDB.rollbackTrack();
|
||||
trackChainDb.rollbackTrack();
|
||||
trackStateDB.rollbackTrack();
|
||||
trackRepository.rollback();
|
||||
return;
|
||||
}
|
||||
|
||||
trackDetailDB.commitTrack();
|
||||
trackChainDb.commitTrack();
|
||||
trackStateDB.commitTrack();
|
||||
|
||||
trackRepository.commit();
|
||||
pendingTransactions.put(Hex.toHexString(tx.getHash()), tx);
|
||||
}
|
||||
|
||||
@ -268,13 +247,11 @@ public class WorldManager {
|
||||
*
|
||||
* @param result
|
||||
* @param gasDebit
|
||||
* @param senderState
|
||||
* @param receiverState
|
||||
* @param senderAddress
|
||||
* @param contractAddress
|
||||
*/
|
||||
private void applyProgramResult(ProgramResult result, BigInteger gasDebit,
|
||||
AccountState senderState, AccountState receiverState,
|
||||
Repository repository,
|
||||
byte[] senderAddress, byte[] contractAddress) {
|
||||
|
||||
if (result.getException() != null &&
|
||||
@ -300,20 +277,17 @@ public class WorldManager {
|
||||
if(stateLogger.isInfoEnabled())
|
||||
stateLogger.info("After contract execution the sender address refunded with gas leftover , \n sender={} \n contract={} \n gas_refund= {}",
|
||||
Hex.toHexString(senderAddress) ,Hex.toHexString(contractAddress), refund);
|
||||
senderState.addToBalance(refund);
|
||||
worldState.update(senderAddress, senderState.getEncoded());
|
||||
|
||||
repository.addBalance(senderAddress, refund);
|
||||
}
|
||||
|
||||
if (bodyCode != null){
|
||||
byte[] codeKey = HashUtil.sha3(bodyCode);
|
||||
chainDB.put(codeKey, bodyCode);
|
||||
receiverState.setCodeHash(codeKey);
|
||||
worldState.update(contractAddress, receiverState.getEncoded());
|
||||
repository.saveCode(contractAddress, bodyCode);
|
||||
|
||||
|
||||
if (stateLogger.isInfoEnabled())
|
||||
stateLogger.info("saving code of the contract to the db:\n contract={} sha3(code)={} code={}",
|
||||
stateLogger.info("saving code of the contract to the db:\n contract={} code={}",
|
||||
Hex.toHexString(contractAddress),
|
||||
Hex.toHexString(codeKey),
|
||||
Hex.toHexString(bodyCode));
|
||||
}
|
||||
|
||||
@ -346,6 +320,6 @@ public class WorldManager {
|
||||
|
||||
public void close() {
|
||||
chainDB.close();
|
||||
stateDB.close();
|
||||
repository.close();
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,8 @@
|
||||
package org.ethereum.vm;
|
||||
|
||||
import org.ethereum.core.AccountState;
|
||||
import org.ethereum.core.ContractDetails;
|
||||
import org.ethereum.crypto.HashUtil;
|
||||
import org.ethereum.db.TrackDatabase;
|
||||
import org.ethereum.manager.WorldManager;
|
||||
import org.ethereum.trie.TrackTrie;
|
||||
import org.ethereum.util.RLP;
|
||||
import org.ethereum.db.ContractDetails;
|
||||
import org.ethereum.db.Repository;
|
||||
import org.ethereum.util.Utils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -14,7 +10,8 @@ import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
@ -28,8 +25,8 @@ public class Program {
|
||||
ProgramListener listener;
|
||||
|
||||
Stack<DataWord> stack = new Stack<DataWord>();
|
||||
Map<DataWord, DataWord> storage = new HashMap<DataWord, DataWord>();
|
||||
ByteBuffer memory = null;
|
||||
byte[] programAddress;
|
||||
|
||||
ProgramResult result = new ProgramResult();
|
||||
|
||||
@ -44,18 +41,14 @@ public class Program {
|
||||
|
||||
gasLogger = LoggerFactory.getLogger("gas - " + invokeData.hashCode());
|
||||
|
||||
result.setStateDb(invokeData.getStateDb());
|
||||
result.setChainDb(invokeData.getChainDb());
|
||||
result.setDetailDB(invokeData.getDetaildDB());
|
||||
result.setRepository(invokeData.getRepository());
|
||||
|
||||
if (ops == null) throw new RuntimeException("program can not run with ops: null");
|
||||
|
||||
this.invokeData = invokeData;
|
||||
this.ops = ops;
|
||||
|
||||
if (invokeData.getStorage() != null){
|
||||
storage = invokeData.getStorage();
|
||||
}
|
||||
programAddress = invokeData.getOwnerAddress().getNoLeadZeroesData();
|
||||
}
|
||||
|
||||
public byte getCurrentOp(){
|
||||
@ -229,22 +222,12 @@ public class Program {
|
||||
// 1. FETCH THE CODE FROM THE MEMORY
|
||||
ByteBuffer programCode = memoryChunk(memStart, memSize);
|
||||
|
||||
TrackTrie stateDB = new TrackTrie( result.getStateDb() );
|
||||
TrackDatabase chainDB = new TrackDatabase( result.getChainDb() );
|
||||
TrackDatabase detailDB = new TrackDatabase( result.getDetailDB() );
|
||||
|
||||
detailDB.startTrack();
|
||||
chainDB.startTrack();
|
||||
stateDB.startTrack();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info("creating a new contract");
|
||||
Repository trackRepository = result.getRepository().getTrack();
|
||||
trackRepository.startTracking();
|
||||
|
||||
byte[] senderAddress = this.getOwnerAddress().getNoLeadZeroesData();
|
||||
|
||||
byte[] data = stateDB.get( senderAddress );
|
||||
AccountState senderState = new AccountState(data);
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info("creating a new contract inside contract run: [{}]", Hex.toHexString(senderAddress));
|
||||
|
||||
// 2.1 PERFORM THE GAS VALUE TX
|
||||
// (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION)
|
||||
@ -259,19 +242,17 @@ public class Program {
|
||||
}
|
||||
|
||||
// 2.2 CREATE THE CONTRACT ADDRESS
|
||||
byte[] nonce = senderState.getNonce().toByteArray();
|
||||
byte[] nonce = trackRepository.getNonce(senderAddress).toByteArray();
|
||||
byte[] newAddress = HashUtil.calcNewAddr(this.getOwnerAddress().getNoLeadZeroesData(), nonce);
|
||||
|
||||
// 2.3 UPDATE THE NONCE
|
||||
// (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION)
|
||||
senderState.incrementNonce();
|
||||
trackRepository.increaseNonce(senderAddress);
|
||||
|
||||
// 3. COOK THE INVOKE AND EXECUTE
|
||||
ProgramInvoke programInvoke =
|
||||
ProgramInvokeFactory.createProgramInvoke(this, DataWord.ZERO, null,
|
||||
DataWord.ZERO, gas, BigInteger.ZERO,
|
||||
null,
|
||||
detailDB, chainDB, stateDB);
|
||||
ProgramInvokeFactory.createProgramInvoke(this, DataWord.ZERO, DataWord.ZERO,
|
||||
gas, BigInteger.ZERO, null, trackRepository);
|
||||
|
||||
VM vm = new VM();
|
||||
Program program = new Program(programCode.array(), programInvoke);
|
||||
@ -282,31 +263,18 @@ public class Program {
|
||||
result.getException() instanceof Program.OutOfGasException){
|
||||
logger.info("contract run halted by OutOfGas: new contract init ={}" , Hex.toHexString(newAddress));
|
||||
|
||||
detailDB.rollbackTrack();
|
||||
chainDB.rollbackTrack();
|
||||
stateDB.rollbackTrack();
|
||||
trackRepository.rollback();
|
||||
stackPushZero();
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. CREATE THE CONTRACT OUT OF RETURN
|
||||
byte[] code = result.getHReturn().array();
|
||||
byte[] keyCode = HashUtil.sha3(code);
|
||||
trackRepository.saveCode(newAddress, code);
|
||||
|
||||
ContractDetails contractDetails = new ContractDetails(program.storage);
|
||||
AccountState state = new AccountState();
|
||||
state.setCodeHash(keyCode);
|
||||
|
||||
stateDB.update(newAddress, state.getEncoded());
|
||||
chainDB.put(keyCode, code);
|
||||
detailDB.put(newAddress, contractDetails.getEncoded());
|
||||
|
||||
// IN SUCCESS PUSH THE ADDRESS IN THE STACK
|
||||
// IN SUCCESS PUSH THE ADDRESS INTO THE STACK
|
||||
stackPush(new DataWord(newAddress));
|
||||
|
||||
detailDB.commitTrack();
|
||||
chainDB.commitTrack();
|
||||
stateDB.commitTrack();
|
||||
trackRepository.commit();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -327,26 +295,11 @@ public class Program {
|
||||
ByteBuffer data = memoryChunk(inDataOffs, inDataSize);
|
||||
|
||||
// FETCH THE SAVED STORAGE
|
||||
ContractDetails details = null;
|
||||
byte[] toAddress = toAddressDW.getNoLeadZeroesData();
|
||||
|
||||
byte[] detailsRLPData = invokeData.getDetaildDB().get(toAddress);
|
||||
if (detailsRLPData != null && detailsRLPData.length > 0)
|
||||
details = new ContractDetails(detailsRLPData);
|
||||
|
||||
AccountState receiverState;
|
||||
byte[] accountData = result.getStateDb().get(toAddress);
|
||||
if (accountData == null || accountData.length == 0){
|
||||
|
||||
logger.info("no saved address in db to call: address={}" ,Hex.toHexString(toAddress));
|
||||
return;
|
||||
} else{
|
||||
|
||||
receiverState = new AccountState(accountData);
|
||||
}
|
||||
|
||||
// FETCH THE CODE
|
||||
byte[] programCode = result.getChainDb().get(receiverState.getCodeHash());
|
||||
byte[] programCode = this.result.getRepository().getCode(toAddress);
|
||||
if (programCode != null && programCode.length != 0){
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
@ -354,14 +307,6 @@ public class Program {
|
||||
Hex.toHexString(toAddress));
|
||||
|
||||
byte[] senderAddress = this.getOwnerAddress().getNoLeadZeroesData();
|
||||
byte[] senderStateB = this.result.getStateDb().get(senderAddress);
|
||||
if (senderStateB == null){
|
||||
logger.info("This should not happen in any case, this inside contract run is is evidence for contract to exist: \n" +
|
||||
"address={}", Hex.toHexString(senderAddress));
|
||||
return;
|
||||
}
|
||||
|
||||
AccountState senderState = new AccountState(senderStateB);
|
||||
|
||||
// 2.1 PERFORM THE GAS VALUE TX
|
||||
// (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION)
|
||||
@ -376,29 +321,19 @@ public class Program {
|
||||
|
||||
// 2.2 UPDATE THE NONCE
|
||||
// (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION)
|
||||
senderState.incrementNonce();
|
||||
this.result.repository.increaseNonce(senderAddress);
|
||||
|
||||
TrackTrie stateDB = new TrackTrie( result.getStateDb() );
|
||||
TrackDatabase chainDB = new TrackDatabase( result.getChainDb() );
|
||||
TrackDatabase detailDB = new TrackDatabase( result.getDetailDB() );
|
||||
|
||||
detailDB.startTrack();
|
||||
chainDB.startTrack();
|
||||
stateDB.startTrack();
|
||||
Repository trackRepository = result.getRepository().getTrack();
|
||||
trackRepository.startTracking();
|
||||
|
||||
// todo: check if the endowment can really be done
|
||||
receiverState.addToBalance(endowmentValue.value());
|
||||
stateDB.update(toAddress, receiverState.getEncoded());
|
||||
|
||||
Map<DataWord, DataWord> storage = null;
|
||||
if (details != null)
|
||||
storage = details.getStorage();
|
||||
trackRepository.addBalance(toAddress, endowmentValue.value());
|
||||
|
||||
ProgramInvoke programInvoke =
|
||||
ProgramInvokeFactory.createProgramInvoke(this, toAddressDW, storage,
|
||||
endowmentValue, gas, receiverState.getBalance(),
|
||||
ProgramInvokeFactory.createProgramInvoke(this, toAddressDW,
|
||||
endowmentValue, gas, result.getRepository().getBalance(toAddress),
|
||||
data.array(),
|
||||
detailDB, chainDB, stateDB);
|
||||
trackRepository);
|
||||
|
||||
VM vm = new VM();
|
||||
Program program = new Program(programCode, programInvoke);
|
||||
@ -409,9 +344,7 @@ public class Program {
|
||||
result.getException() instanceof Program.OutOfGasException){
|
||||
logger.info("contract run halted by OutOfGas: contract={}" , Hex.toHexString(toAddress));
|
||||
|
||||
detailDB.rollbackTrack();
|
||||
chainDB.rollbackTrack();
|
||||
stateDB.rollbackTrack();
|
||||
trackRepository.rollback();
|
||||
stackPushZero();
|
||||
return;
|
||||
}
|
||||
@ -434,9 +367,7 @@ public class Program {
|
||||
// 4. THE FLAG OF SUCCESS IS ONE PUSHED INTO THE STACK
|
||||
stackPushOne();
|
||||
|
||||
detailDB.commitTrack();
|
||||
chainDB.commitTrack();
|
||||
stateDB.commitTrack();
|
||||
trackRepository.commit();
|
||||
stackPush(new DataWord(1));
|
||||
|
||||
// the gas spent in any internal outcome
|
||||
@ -444,13 +375,6 @@ public class Program {
|
||||
spendGas(result.getGasUsed(), " 'Total for CALL run' ");
|
||||
logger.info("The usage of the gas in external call updated", result.getGasUsed());
|
||||
|
||||
// update the storage , it could
|
||||
// change by the call
|
||||
byte[] contractDetailBytes =
|
||||
result.getDetailDB().get(getOwnerAddress().getNoLeadZeroesData());
|
||||
if (contractDetailBytes != null){
|
||||
this.storage = new ContractDetails(contractDetailBytes).getStorage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -473,12 +397,7 @@ public class Program {
|
||||
public void storageSave(byte[] key, byte[] val){
|
||||
DataWord keyWord = new DataWord(key);
|
||||
DataWord valWord = new DataWord(val);
|
||||
storage.put(keyWord, valWord);
|
||||
|
||||
if (storage != null){
|
||||
ContractDetails contractDetails = new ContractDetails(storage);
|
||||
result.getDetailDB().put(getOwnerAddress().getNoLeadZeroesData() , contractDetails.getEncoded());
|
||||
}
|
||||
result.repository.addStorageRow(this.programAddress, keyWord, valWord);
|
||||
}
|
||||
|
||||
public DataWord getOwnerAddress(){
|
||||
@ -536,7 +455,7 @@ public class Program {
|
||||
}
|
||||
|
||||
public DataWord storageLoad(DataWord key){
|
||||
return storage.get(key);
|
||||
return result.repository.getStorageValue(this.programAddress, key);
|
||||
}
|
||||
|
||||
public DataWord getPrevHash(){
|
||||
@ -584,10 +503,12 @@ public class Program {
|
||||
}
|
||||
if (stackData.length() > 0) stackData.insert(0, "\n");
|
||||
|
||||
ContractDetails contractDetails = this.result.getRepository().getContractDetails(this.programAddress);
|
||||
StringBuilder storageData = new StringBuilder();
|
||||
for (DataWord key : storage.keySet()){
|
||||
for (DataWord key : contractDetails.getStorage().keySet()){
|
||||
|
||||
storageData.append(" ").append(key).append(" -> ").append(storage.get(key)).append("\n");
|
||||
storageData.append(" ").append(key).append(" -> ").
|
||||
append(contractDetails.getStorage().get(key)).append("\n");
|
||||
}
|
||||
if (storageData.length() > 0) storageData.insert(0, "\n");
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package org.ethereum.vm;
|
||||
|
||||
import org.ethereum.db.Repository;
|
||||
import org.ethereum.db.TrackDatabase;
|
||||
import org.ethereum.trie.TrackTrie;
|
||||
|
||||
@ -32,11 +33,7 @@ public interface ProgramInvoke {
|
||||
public DataWord getDifficulty();
|
||||
public DataWord getGaslimit();
|
||||
|
||||
public Map<DataWord, DataWord> getStorage();
|
||||
|
||||
public TrackDatabase getDetaildDB();
|
||||
public TrackDatabase getChainDb();
|
||||
public TrackTrie getStateDb();
|
||||
public Repository getRepository();
|
||||
|
||||
public boolean byTransaction();
|
||||
|
||||
|
@ -1,18 +1,13 @@
|
||||
package org.ethereum.vm;
|
||||
|
||||
import org.ethereum.core.AccountState;
|
||||
import org.ethereum.core.Block;
|
||||
import org.ethereum.core.ContractDetails;
|
||||
import org.ethereum.core.Transaction;
|
||||
import org.ethereum.db.TrackDatabase;
|
||||
import org.ethereum.manager.WorldManager;
|
||||
import org.ethereum.trie.TrackTrie;
|
||||
import org.ethereum.db.Repository;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
@ -26,8 +21,7 @@ public class ProgramInvokeFactory {
|
||||
private static Logger logger = LoggerFactory.getLogger("VM");
|
||||
|
||||
// Invocation by the wire tx
|
||||
public static ProgramInvoke createProgramInvoke(Transaction tx, Block lastBlock, ContractDetails details,
|
||||
TrackDatabase detaildDB, TrackDatabase chainDb, TrackTrie stateDB){
|
||||
public static ProgramInvoke createProgramInvoke(Transaction tx, Block lastBlock, Repository repository){
|
||||
|
||||
// https://ethereum.etherpad.mozilla.org/26
|
||||
|
||||
@ -44,13 +38,7 @@ public class ProgramInvokeFactory {
|
||||
byte[] caller = tx.getSender();
|
||||
|
||||
/*** BALANCE op ***/
|
||||
byte[] addressStateData = stateDB.get(address);
|
||||
|
||||
byte[] balance = null;
|
||||
if (addressStateData.length == 0)
|
||||
balance = new byte[]{0};
|
||||
else
|
||||
balance = new AccountState(addressStateData).getBalance().toByteArray();
|
||||
byte[] balance = repository.getBalance(address).toByteArray();
|
||||
|
||||
|
||||
/*** GASPRICE op ***/
|
||||
@ -87,14 +75,8 @@ public class ProgramInvokeFactory {
|
||||
/*** GASLIMIT op ***/
|
||||
long gaslimit = lastBlock.getGasLimit();
|
||||
|
||||
/*** Map of storage values ***/
|
||||
Map<DataWord, DataWord> storage = null;
|
||||
if (details != null)
|
||||
storage = details.getStorage();
|
||||
|
||||
detaildDB.startTrack();
|
||||
chainDb.startTrack();
|
||||
stateDB.startTrack();
|
||||
repository.startTracking();
|
||||
|
||||
if (logger.isInfoEnabled()){
|
||||
logger.info("Program invocation: \n" +
|
||||
@ -132,8 +114,8 @@ public class ProgramInvokeFactory {
|
||||
|
||||
ProgramInvoke programInvoke =
|
||||
new ProgramInvokeImpl(address, origin, caller, balance, gasPrice, gas, callValue, data,
|
||||
lastHash, coinbase, timestamp, number, difficulty, gaslimit, storage,
|
||||
detaildDB, chainDb, stateDB);
|
||||
lastHash, coinbase, timestamp, number, difficulty, gaslimit,
|
||||
repository);
|
||||
|
||||
return programInvoke;
|
||||
}
|
||||
@ -143,10 +125,9 @@ public class ProgramInvokeFactory {
|
||||
* This invocation created for contract call contract
|
||||
*/
|
||||
public static ProgramInvoke createProgramInvoke(Program program, DataWord toAddress,
|
||||
Map<DataWord, DataWord> storageIn,
|
||||
DataWord inValue, DataWord inGas,
|
||||
BigInteger balanceInt, byte[] dataIn,
|
||||
TrackDatabase detailDB, TrackDatabase chainDB, TrackTrie stateDB){
|
||||
Repository repository){
|
||||
|
||||
|
||||
DataWord address = toAddress;
|
||||
@ -166,8 +147,6 @@ public class ProgramInvokeFactory {
|
||||
DataWord difficulty = program.getDifficulty();
|
||||
DataWord gasLimit = program.getGaslimit();
|
||||
|
||||
Map<DataWord, DataWord> storage = storageIn;
|
||||
|
||||
if (logger.isInfoEnabled()){
|
||||
|
||||
logger.info("Program invocation: \n" +
|
||||
@ -204,7 +183,7 @@ public class ProgramInvokeFactory {
|
||||
|
||||
return new ProgramInvokeImpl(address, origin, caller, balance, gasPrice, gas, callValue,
|
||||
data, lastHash, coinbase, timestamp, number, difficulty, gasLimit,
|
||||
storage, detailDB, chainDB, stateDB);
|
||||
repository);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package org.ethereum.vm;
|
||||
|
||||
import org.ethereum.db.Repository;
|
||||
import org.ethereum.db.TrackDatabase;
|
||||
import org.ethereum.trie.TrackTrie;
|
||||
import org.ethereum.util.ByteUtil;
|
||||
@ -36,16 +37,13 @@ public class ProgramInvokeImpl implements ProgramInvoke {
|
||||
|
||||
Map<DataWord, DataWord> storage;
|
||||
|
||||
TrackDatabase detaildDB;
|
||||
TrackDatabase chainDb;
|
||||
TrackTrie stateDb;
|
||||
Repository repository;
|
||||
private boolean byTransaction = true;
|
||||
|
||||
public ProgramInvokeImpl(DataWord address, DataWord origin, DataWord caller, DataWord balance,
|
||||
DataWord gasPrice, DataWord gas, DataWord callValue, byte[] msgData,
|
||||
DataWord lastHash, DataWord coinbase, DataWord timestamp, DataWord number, DataWord difficulty,
|
||||
DataWord gaslimit, Map<DataWord, DataWord> storage,
|
||||
TrackDatabase detaildDB, TrackDatabase chainDb, TrackTrie stateDB) {
|
||||
DataWord gaslimit, Repository repository) {
|
||||
|
||||
// Transaction env
|
||||
this.address = address;
|
||||
@ -67,9 +65,7 @@ public class ProgramInvokeImpl implements ProgramInvoke {
|
||||
|
||||
this.storage = storage;
|
||||
|
||||
this.detaildDB = detaildDB;
|
||||
this.chainDb = chainDb;
|
||||
this.stateDb = stateDB;
|
||||
this.repository = repository;
|
||||
this.byTransaction = false;
|
||||
|
||||
}
|
||||
@ -78,8 +74,8 @@ public class ProgramInvokeImpl implements ProgramInvoke {
|
||||
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, Map<DataWord, DataWord> storage,
|
||||
TrackDatabase detaildDB, TrackDatabase chainDb, TrackTrie stateDB) {
|
||||
long gaslimit,
|
||||
Repository repository) {
|
||||
|
||||
// Transaction env
|
||||
this.address = new DataWord(address);
|
||||
@ -101,9 +97,7 @@ public class ProgramInvokeImpl implements ProgramInvoke {
|
||||
|
||||
this.storage = storage;
|
||||
|
||||
this.detaildDB = detaildDB;
|
||||
this.chainDb = chainDb;
|
||||
this.stateDb = stateDB;
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
/* ADDRESS op */
|
||||
@ -225,17 +219,8 @@ public class ProgramInvokeImpl implements ProgramInvoke {
|
||||
/* Storage */
|
||||
public Map<DataWord, DataWord> getStorage(){ return storage; }
|
||||
|
||||
|
||||
public TrackDatabase getDetaildDB() {
|
||||
return detaildDB;
|
||||
}
|
||||
|
||||
public TrackDatabase getChainDb() {
|
||||
return chainDb;
|
||||
}
|
||||
|
||||
public TrackTrie getStateDb() {
|
||||
return stateDb;
|
||||
public Repository getRepository() {
|
||||
return repository;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -255,9 +240,7 @@ public class ProgramInvokeImpl implements ProgramInvoke {
|
||||
if (balance != null ? !balance.equals(that.balance) : that.balance != null) return false;
|
||||
if (callValue != null ? !callValue.equals(that.callValue) : that.callValue != null) return false;
|
||||
if (caller != null ? !caller.equals(that.caller) : that.caller != null) return false;
|
||||
if (chainDb != null ? !chainDb.equals(that.chainDb) : that.chainDb != null) return false;
|
||||
if (coinbase != null ? !coinbase.equals(that.coinbase) : that.coinbase != null) return false;
|
||||
if (detaildDB != null ? !detaildDB.equals(that.detaildDB) : that.detaildDB != null) return false;
|
||||
if (difficulty != null ? !difficulty.equals(that.difficulty) : that.difficulty != null) return false;
|
||||
if (gas != null ? !gas.equals(that.gas) : that.gas != null) return false;
|
||||
if (gasPrice != null ? !gasPrice.equals(that.gasPrice) : that.gasPrice != null) return false;
|
||||
@ -266,7 +249,7 @@ public class ProgramInvokeImpl implements ProgramInvoke {
|
||||
if (number != null ? !number.equals(that.number) : that.number != null) return false;
|
||||
if (origin != null ? !origin.equals(that.origin) : that.origin != null) return false;
|
||||
if (prevHash != null ? !prevHash.equals(that.prevHash) : that.prevHash != null) return false;
|
||||
if (stateDb != null ? !stateDb.equals(that.stateDb) : that.stateDb != null) return false;
|
||||
if (repository != null ? !repository.equals(that.repository) : that.repository != null) return false;
|
||||
if (storage != null ? !storage.equals(that.storage) : that.storage != null) return false;
|
||||
if (timestamp != null ? !timestamp.equals(that.timestamp) : that.timestamp != null) return false;
|
||||
|
||||
@ -290,9 +273,7 @@ public class ProgramInvokeImpl implements ProgramInvoke {
|
||||
result = 31 * result + (difficulty != null ? difficulty.hashCode() : 0);
|
||||
result = 31 * result + (gaslimit != null ? gaslimit.hashCode() : 0);
|
||||
result = 31 * result + (storage != null ? storage.hashCode() : 0);
|
||||
result = 31 * result + (detaildDB != null ? detaildDB.hashCode() : 0);
|
||||
result = 31 * result + (chainDb != null ? chainDb.hashCode() : 0);
|
||||
result = 31 * result + (stateDb != null ? stateDb.hashCode() : 0);
|
||||
result = 31 * result + (repository!= null ? repository.hashCode() : 0);
|
||||
result = 31 * result + (byTransaction ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
|
@ -1,15 +1,10 @@
|
||||
package org.ethereum.vm;
|
||||
|
||||
import org.ethereum.core.ContractDetails;
|
||||
import org.ethereum.crypto.ECKey;
|
||||
import org.ethereum.crypto.HashUtil;
|
||||
import org.ethereum.db.TrackDatabase;
|
||||
import org.ethereum.manager.WorldManager;
|
||||
import org.ethereum.trie.TrackTrie;
|
||||
import org.ethereum.db.Repository;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
* @author: Roman Mandeleil
|
||||
@ -20,20 +15,18 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
|
||||
|
||||
byte[] msgData;
|
||||
|
||||
TrackTrie stateDB = null;
|
||||
TrackDatabase chainDb = null;
|
||||
TrackDatabase detaildDB = null;
|
||||
|
||||
ContractDetails details = null;
|
||||
|
||||
String ownerAddress;
|
||||
Repository repository = null;
|
||||
String ownerAddress = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||
|
||||
|
||||
public ProgramInvokeMockImpl(byte[] msgDataRaw){
|
||||
this();
|
||||
this.msgData = msgDataRaw;
|
||||
}
|
||||
|
||||
public ProgramInvokeMockImpl() {
|
||||
this.repository = new Repository();
|
||||
this.repository.createAccount(Hex.decode(ownerAddress));
|
||||
}
|
||||
|
||||
/* ADDRESS op */
|
||||
@ -171,51 +164,21 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
|
||||
return new DataWord(gasLimit);
|
||||
}
|
||||
|
||||
|
||||
public void setStateDB(TrackTrie stateDB) {
|
||||
this.stateDB = stateDB;
|
||||
}
|
||||
|
||||
public void setChainDb(TrackDatabase chainDb) {
|
||||
this.chainDb = chainDb;
|
||||
}
|
||||
|
||||
public void setDetaildDB(TrackDatabase detaildDB) {
|
||||
this.detaildDB = detaildDB;
|
||||
}
|
||||
|
||||
public void setDetails(ContractDetails details) {
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
public void setOwnerAddress(String ownerAddress) {
|
||||
this.ownerAddress = ownerAddress;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Map<DataWord, DataWord> getStorage() {
|
||||
if (details == null) return null;
|
||||
return details.getStorage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackDatabase getDetaildDB() {
|
||||
return detaildDB;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackDatabase getChainDb() {
|
||||
return chainDb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackTrie getStateDb() {
|
||||
return stateDB;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean byTransaction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Repository getRepository() {
|
||||
return this.repository;
|
||||
}
|
||||
|
||||
public void setRepository(Repository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package org.ethereum.vm;
|
||||
|
||||
import org.ethereum.db.Repository;
|
||||
import org.ethereum.db.TrackDatabase;
|
||||
import org.ethereum.trie.TrackTrie;
|
||||
|
||||
@ -18,9 +19,7 @@ public class ProgramResult {
|
||||
private ByteBuffer hReturn = null;
|
||||
private RuntimeException exception;
|
||||
|
||||
TrackDatabase detailDB;
|
||||
TrackDatabase chainDb;
|
||||
TrackTrie stateDb;
|
||||
Repository repository = null;
|
||||
|
||||
public void spendGas(int gas){
|
||||
gasUsed += gas;
|
||||
@ -48,27 +47,11 @@ public class ProgramResult {
|
||||
this.exception = exception;
|
||||
}
|
||||
|
||||
public TrackDatabase getDetailDB() {
|
||||
return detailDB;
|
||||
public Repository getRepository() {
|
||||
return repository;
|
||||
}
|
||||
|
||||
public void setDetailDB(TrackDatabase detailDB) {
|
||||
this.detailDB = detailDB;
|
||||
}
|
||||
|
||||
public TrackDatabase getChainDb() {
|
||||
return chainDb;
|
||||
}
|
||||
|
||||
public void setChainDb(TrackDatabase chainDb) {
|
||||
this.chainDb = chainDb;
|
||||
}
|
||||
|
||||
public TrackTrie getStateDb() {
|
||||
return stateDb;
|
||||
}
|
||||
|
||||
public void setStateDb(TrackTrie stateDb) {
|
||||
this.stateDb = stateDb;
|
||||
public void setRepository(Repository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
}
|
||||
|
@ -1,90 +0,0 @@
|
||||
package org.ethereum.core;
|
||||
|
||||
import org.ethereum.vm.DataWord;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
*
|
||||
* @author: Roman Mandeleil
|
||||
* Created on: 09/06/2014 15:41
|
||||
*/
|
||||
|
||||
public class ContractDetailsTest {
|
||||
|
||||
@Test /* encode 2 keys/values */
|
||||
public void test1(){
|
||||
|
||||
String expected = "f888f842a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000001f842a00000000000000000000000000000000000000000000000000000000000009dd4a0000000000000000000000000000000000000000000000000000000000000765f";
|
||||
|
||||
DataWord key1 = new DataWord(1);
|
||||
DataWord value1 = new DataWord(30303);
|
||||
|
||||
DataWord key2 = new DataWord(2);
|
||||
DataWord value2 = new DataWord(40404);
|
||||
|
||||
|
||||
HashMap<DataWord, DataWord> storage = new HashMap<>();
|
||||
storage.put(key1, value1);
|
||||
storage.put(key2, value2);
|
||||
|
||||
ContractDetails contractDetails = new ContractDetails(storage);
|
||||
|
||||
String encoded = Hex.toHexString(contractDetails.getEncoded());
|
||||
|
||||
Assert.assertEquals(expected, encoded);
|
||||
}
|
||||
|
||||
@Test /* encode 3 keys/values */
|
||||
public void test2(){
|
||||
|
||||
String expected = "f8caf863a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000003f863a00000000000000000000000000000000000000000000000000000000000009dd4a0000000000000000000000000000000000000000000000000000000000000765fa0000000000000000000000000000000000000000000000000000000000000ffff";
|
||||
|
||||
DataWord key1 = new DataWord(1);
|
||||
DataWord value1 = new DataWord(30303);
|
||||
|
||||
DataWord key2 = new DataWord(2);
|
||||
DataWord value2 = new DataWord(40404);
|
||||
|
||||
DataWord key3 = new DataWord(3);
|
||||
DataWord value3 = new DataWord(0xFFFF);
|
||||
|
||||
HashMap<DataWord, DataWord> storage = new HashMap<>();
|
||||
storage.put(key1, value1);
|
||||
storage.put(key2, value2);
|
||||
storage.put(key3, value3);
|
||||
|
||||
ContractDetails contractDetails = new ContractDetails(storage);
|
||||
|
||||
String encoded = Hex.toHexString(contractDetails.getEncoded());
|
||||
|
||||
Assert.assertEquals(expected, encoded);
|
||||
}
|
||||
|
||||
@Test /* decode 3 keys/values */
|
||||
public void test3(){
|
||||
|
||||
String rlpData = "f8caf863a00000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000003f863a00000000000000000000000000000000000000000000000000000000000009dd4a0000000000000000000000000000000000000000000000000000000000000765fa0000000000000000000000000000000000000000000000000000000000000ffff";
|
||||
ContractDetails contractDetails = new ContractDetails(Hex.decode(rlpData));
|
||||
|
||||
String expKey3String = "0000000000000000000000000000000000000000000000000000000000000003";
|
||||
String expVal3String = "000000000000000000000000000000000000000000000000000000000000ffff";
|
||||
|
||||
DataWord key3 = contractDetails.storageKeys.get(2);
|
||||
DataWord value3 = contractDetails.storageValues.get(2);
|
||||
|
||||
String key3String = Hex.toHexString(key3.getData());
|
||||
String value3String = Hex.toHexString(value3.getData());
|
||||
|
||||
Assert.assertEquals(expKey3String, key3String);
|
||||
Assert.assertEquals(expVal3String, value3String);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
package org.ethereum.db;
|
||||
|
||||
import org.ethereum.core.AccountState;
|
||||
import org.ethereum.core.ContractDetails;
|
||||
import org.ethereum.vm.DataWord;
|
||||
import org.junit.*;
|
||||
import org.junit.runners.MethodSorters;
|
||||
|
@ -1,17 +1,14 @@
|
||||
package org.ethereum.vm;
|
||||
|
||||
import org.abego.treelayout.internal.util.Contract;
|
||||
import org.ethereum.core.AccountState;
|
||||
import org.ethereum.core.ContractDetails;
|
||||
import org.ethereum.crypto.HashUtil;
|
||||
import org.ethereum.db.TrackDatabase;
|
||||
import org.ethereum.manager.WorldManager;
|
||||
import org.ethereum.trie.TrackTrie;
|
||||
import org.ethereum.db.Repository;
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Test;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.HashMap;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@ -22,6 +19,7 @@ import static org.junit.Assert.assertEquals;
|
||||
* Created on: 16/06/2014 10:37
|
||||
*/
|
||||
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
public class VMComplexTest {
|
||||
|
||||
|
||||
@ -47,12 +45,6 @@ public class VMComplexTest {
|
||||
DataWord key1 = new DataWord(999);
|
||||
DataWord value1 = new DataWord(3);
|
||||
|
||||
HashMap<DataWord, DataWord> storage = new HashMap<>();
|
||||
storage.put(key1, value1);
|
||||
|
||||
ContractDetails contractDetails = new ContractDetails(storage);
|
||||
|
||||
|
||||
// Set contract into Database
|
||||
String callerAddr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||
String contractAddr = "77045e71a7a2c50903d88e564cd72fab11e82051";
|
||||
@ -66,24 +58,18 @@ public class VMComplexTest {
|
||||
AccountState accountState = new AccountState();
|
||||
accountState.setCodeHash(codeKey);
|
||||
|
||||
AccountState callerAcountState = new AccountState();
|
||||
callerAcountState.addToBalance(new BigInteger("100000000000000000000"));
|
||||
|
||||
WorldManager.instance.worldState.update(callerAddrB, callerAcountState.getEncoded());
|
||||
WorldManager.instance.worldState.update(contractAddrB, accountState.getEncoded());
|
||||
WorldManager.instance.chainDB.put(codeKey, codeB);
|
||||
WorldManager.instance.detaildDB.put(contractAddrB, contractDetails.getEncoded());
|
||||
|
||||
TrackTrie stateDB = new TrackTrie(WorldManager.instance.worldState);
|
||||
TrackDatabase chainDb = new TrackDatabase(WorldManager.instance.chainDB);
|
||||
TrackDatabase detaildDB = new TrackDatabase(WorldManager.instance.detaildDB);
|
||||
|
||||
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
||||
pi.setDetaildDB(detaildDB);
|
||||
pi.setChainDb(chainDb);
|
||||
pi.setStateDB(stateDB);
|
||||
pi.setDetails(contractDetails);
|
||||
pi.setOwnerAddress("77045e71a7a2c50903d88e564cd72fab11e82051");
|
||||
Repository repository = pi.getRepository();
|
||||
|
||||
repository.createAccount(callerAddrB);
|
||||
repository.addBalance(callerAddrB, new BigInteger("100000000000000000000"));
|
||||
|
||||
repository.createAccount(contractAddrB);
|
||||
repository.saveCode(contractAddrB, codeB);
|
||||
repository.addStorageRow(contractAddrB, key1, value1);
|
||||
|
||||
|
||||
|
||||
|
||||
// Play the program
|
||||
@ -100,15 +86,15 @@ public class VMComplexTest {
|
||||
|
||||
System.out.println();
|
||||
System.out.println("============ Results ============");
|
||||
AccountState as =
|
||||
new AccountState(WorldManager.instance.worldState.get(
|
||||
Hex.decode( contractAddr) ));
|
||||
|
||||
BigInteger balance = repository.getBalance(callerAddrB);
|
||||
|
||||
System.out.println("*** Used gas: " + program.result.getGasUsed());
|
||||
System.out.println("*** Contract Balance: " + as.getBalance());
|
||||
System.out.println("*** Contract Balance: " + balance);
|
||||
|
||||
// todo: assert caller balance after contract exec
|
||||
|
||||
repository.close();
|
||||
assertEquals(expectedGas, program.result.getGasUsed());
|
||||
}
|
||||
|
||||
@ -153,34 +139,23 @@ public class VMComplexTest {
|
||||
|
||||
byte[] contractA_addr_bytes = Hex.decode(contractA_addr);
|
||||
byte[] codeA = Hex.decode(code_a);
|
||||
byte[] codeA_Key = HashUtil.sha3(codeA);
|
||||
AccountState accountState_a = new AccountState();
|
||||
accountState_a.setCodeHash(codeA_Key);
|
||||
WorldManager.instance.worldState.update(contractA_addr_bytes, accountState_a.getEncoded());
|
||||
|
||||
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
||||
pi.setOwnerAddress(contractB_addr);
|
||||
Repository repository = pi.repository;
|
||||
|
||||
byte[] contractB_addr_bytes = Hex.decode(contractB_addr);
|
||||
byte[] codeB = Hex.decode(code_b);
|
||||
byte[] codeB_Key = HashUtil.sha3(codeB);
|
||||
AccountState accountState_b = new AccountState();
|
||||
accountState_b.setCodeHash(codeB_Key);
|
||||
WorldManager.instance.worldState.update(contractB_addr_bytes, accountState_a.getEncoded());
|
||||
|
||||
AccountState callerAcountState = new AccountState();
|
||||
callerAcountState.addToBalance(new BigInteger("100000000000000000000"));
|
||||
WorldManager.instance.worldState.update(caller_addr_bytes, callerAcountState.getEncoded());
|
||||
repository.createAccount(contractA_addr_bytes);
|
||||
repository.saveCode(contractA_addr_bytes, codeA);
|
||||
|
||||
WorldManager.instance.chainDB.put(codeA_Key, codeA);
|
||||
repository.createAccount(contractB_addr_bytes);
|
||||
repository.saveCode(contractB_addr_bytes, codeB);
|
||||
|
||||
TrackTrie stateDB = new TrackTrie(WorldManager.instance.worldState);
|
||||
TrackDatabase chainDb = new TrackDatabase(WorldManager.instance.chainDB);
|
||||
TrackDatabase detaildDB = new TrackDatabase(WorldManager.instance.detaildDB);
|
||||
repository.createAccount(caller_addr_bytes);
|
||||
repository.addBalance(caller_addr_bytes, new BigInteger("100000000000000000000"));
|
||||
|
||||
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
||||
pi.setDetaildDB(detaildDB);
|
||||
pi.setChainDb(chainDb);
|
||||
pi.setStateDB(stateDB);
|
||||
pi.setDetails(null);
|
||||
pi.setOwnerAddress(contractB_addr);
|
||||
|
||||
// ****************** //
|
||||
// Play the program //
|
||||
@ -198,27 +173,20 @@ public class VMComplexTest {
|
||||
|
||||
System.out.println();
|
||||
System.out.println("============ Results ============");
|
||||
AccountState as =
|
||||
new AccountState(WorldManager.instance.worldState.get(
|
||||
Hex.decode( contractA_addr) ));
|
||||
|
||||
|
||||
System.out.println("*** Used gas: " + program.result.getGasUsed());
|
||||
|
||||
|
||||
byte[] rlpBytes = WorldManager.instance.detaildDB.get(contractA_addr_bytes);
|
||||
|
||||
ContractDetails details = new ContractDetails(rlpBytes);
|
||||
DataWord value_1 = details.getStorage().get(new DataWord(00));
|
||||
DataWord value_2 = details.getStorage().get(new DataWord(01));
|
||||
DataWord value_1 = repository.getStorageValue(contractA_addr_bytes, new DataWord(00));
|
||||
DataWord value_2 = repository.getStorageValue(contractA_addr_bytes, new DataWord(01));
|
||||
|
||||
|
||||
repository.close();
|
||||
assertEquals(expectedVal_1, value_1.longValue());
|
||||
assertEquals(expectedVal_2, value_2.longValue());
|
||||
|
||||
// todo: check that the value pushed after exec is 1
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -270,34 +238,22 @@ public class VMComplexTest {
|
||||
|
||||
byte[] contractA_addr_bytes = Hex.decode(contractA_addr);
|
||||
byte[] codeA = Hex.decode(code_a);
|
||||
byte[] codeA_Key = HashUtil.sha3(codeA);
|
||||
AccountState accountState_a = new AccountState();
|
||||
accountState_a.setCodeHash(codeA_Key);
|
||||
WorldManager.instance.worldState.update(contractA_addr_bytes, accountState_a.getEncoded());
|
||||
|
||||
byte[] contractB_addr_bytes = Hex.decode(contractB_addr);
|
||||
byte[] codeB = Hex.decode(code_b);
|
||||
byte[] codeB_Key = HashUtil.sha3(codeB);
|
||||
AccountState accountState_b = new AccountState();
|
||||
accountState_b.setCodeHash(codeB_Key);
|
||||
WorldManager.instance.worldState.update(contractB_addr_bytes, accountState_a.getEncoded());
|
||||
|
||||
AccountState callerAcountState = new AccountState();
|
||||
callerAcountState.addToBalance(new BigInteger("100000000000000000000"));
|
||||
WorldManager.instance.worldState.update(caller_addr_bytes, callerAcountState.getEncoded());
|
||||
|
||||
WorldManager.instance.chainDB.put(codeA_Key, codeA);
|
||||
|
||||
TrackTrie stateDB = new TrackTrie(WorldManager.instance.worldState);
|
||||
TrackDatabase chainDb = new TrackDatabase(WorldManager.instance.chainDB);
|
||||
TrackDatabase detaildDB = new TrackDatabase(WorldManager.instance.detaildDB);
|
||||
|
||||
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
||||
pi.setDetaildDB(detaildDB);
|
||||
pi.setChainDb(chainDb);
|
||||
pi.setStateDB(stateDB);
|
||||
pi.setDetails(null);
|
||||
pi.setOwnerAddress(contractB_addr);
|
||||
Repository repository = pi.getRepository();
|
||||
repository.createAccount(contractA_addr_bytes);
|
||||
repository.saveCode(contractA_addr_bytes, codeA);
|
||||
|
||||
repository.createAccount(contractB_addr_bytes);
|
||||
repository.saveCode(contractB_addr_bytes, codeB);
|
||||
|
||||
repository.createAccount(caller_addr_bytes);
|
||||
repository.addBalance(caller_addr_bytes, new BigInteger("100000000000000000000"));
|
||||
|
||||
|
||||
// ****************** //
|
||||
// Play the program //
|
||||
@ -312,12 +268,8 @@ public class VMComplexTest {
|
||||
program.setRuntimeFailure(e);
|
||||
}
|
||||
|
||||
|
||||
System.out.println();
|
||||
System.out.println("============ Results ============");
|
||||
AccountState as =
|
||||
new AccountState(WorldManager.instance.worldState.get(
|
||||
Hex.decode( contractA_addr) ));
|
||||
|
||||
|
||||
System.out.println("*** Used gas: " + program.result.getGasUsed());
|
||||
@ -329,6 +281,8 @@ public class VMComplexTest {
|
||||
DataWord value5 = program.memoryLoad(new DataWord(160));
|
||||
DataWord value6 = program.memoryLoad(new DataWord(192));
|
||||
|
||||
repository.close();
|
||||
|
||||
assertEquals(expectedVal_1, value1.longValue());
|
||||
assertEquals(expectedVal_2, value2.longValue());
|
||||
assertEquals(expectedVal_3, value3.longValue());
|
||||
@ -337,7 +291,6 @@ public class VMComplexTest {
|
||||
assertEquals(expectedVal_6, value6.longValue());
|
||||
|
||||
// todo: check that the value pushed after exec is 1
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -374,31 +327,20 @@ public class VMComplexTest {
|
||||
"005460206000f2000000000000000000000000" +
|
||||
"0000000000000000000000602054602960006064f0";
|
||||
|
||||
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
||||
pi.setOwnerAddress(contractA_addr);
|
||||
|
||||
Repository repository = pi.repository;
|
||||
|
||||
byte[] caller_addr_bytes = Hex.decode(callerAddr);
|
||||
|
||||
byte[] contractA_addr_bytes = Hex.decode(contractA_addr);
|
||||
byte[] codeA = Hex.decode(code_a);
|
||||
byte[] codeA_Key = HashUtil.sha3(codeA);
|
||||
AccountState accountState_a = new AccountState();
|
||||
accountState_a.setCodeHash(codeA_Key);
|
||||
WorldManager.instance.worldState.update(contractA_addr_bytes, accountState_a.getEncoded());
|
||||
|
||||
AccountState callerAcountState = new AccountState();
|
||||
callerAcountState.addToBalance(new BigInteger("100000000000000000000"));
|
||||
WorldManager.instance.worldState.update(caller_addr_bytes, callerAcountState.getEncoded());
|
||||
repository.createAccount(contractA_addr_bytes);
|
||||
repository.saveCode(contractA_addr_bytes, codeA);
|
||||
|
||||
WorldManager.instance.chainDB.put(codeA_Key, codeA);
|
||||
|
||||
TrackTrie stateDB = new TrackTrie(WorldManager.instance.worldState);
|
||||
TrackDatabase chainDb = new TrackDatabase(WorldManager.instance.chainDB);
|
||||
TrackDatabase detaildDB = new TrackDatabase(WorldManager.instance.detaildDB);
|
||||
|
||||
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
|
||||
pi.setDetaildDB(detaildDB);
|
||||
pi.setChainDb(chainDb);
|
||||
pi.setStateDB(stateDB);
|
||||
pi.setDetails(null);
|
||||
pi.setOwnerAddress(contractA_addr);
|
||||
repository.createAccount(caller_addr_bytes);
|
||||
|
||||
// ****************** //
|
||||
// Play the program //
|
||||
@ -416,16 +358,11 @@ public class VMComplexTest {
|
||||
|
||||
System.out.println();
|
||||
System.out.println("============ Results ============");
|
||||
AccountState as =
|
||||
new AccountState(WorldManager.instance.worldState.get(
|
||||
Hex.decode( contractA_addr) ));
|
||||
|
||||
|
||||
System.out.println("*** Used gas: " + program.result.getGasUsed());
|
||||
|
||||
|
||||
// todo: check that the value pushed after exec is the new address
|
||||
|
||||
repository.close();
|
||||
}
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user