Merge pull request #61 from nicksavers/master

Apply blockReward after txs and for uncles
This commit is contained in:
romanman 2014-07-11 15:07:56 +03:00
commit 82c0d2ceab
7 changed files with 231 additions and 264 deletions

View File

@ -118,7 +118,6 @@ public class Blockchain {
if(!blockStateRootHash.equals(worldStateRootHash)) if(!blockStateRootHash.equals(worldStateRootHash))
logger.warn("WARNING: STATE CONFLICT! worldstate {} mismatch", worldStateRootHash); logger.warn("WARNING: STATE CONFLICT! worldstate {} mismatch", worldStateRootHash);
} }
} }
// Remove all wallet transactions as they already approved by the net // Remove all wallet transactions as they already approved by the net
for (Block block : blocks) { for (Block block : blocks) {

View File

@ -35,9 +35,7 @@ public class ProgramPlayDialog extends JPanel implements ActionListener,
VM vm = new VM(); VM vm = new VM();
ProgramInvoke pi = new ProgramInvokeMockImpl(); ProgramInvoke pi = new ProgramInvokeMockImpl();
Program program = new Program(code, pi);
Program program = new Program(code ,
pi);
program.addListener(this); program.addListener(this);
program.fullTrace(); program.fullTrace();

View File

@ -77,9 +77,6 @@ public class WorldManager {
if (blockchain != null) if (blockchain != null)
blockchain.addWalletTransaction(tx); blockchain.addWalletTransaction(tx);
// TODO: what is going on with simple wallet transfer ?
// 1. VALIDATE THE NONCE
byte[] senderAddress = tx.getSender(); byte[] senderAddress = tx.getSender();
AccountState senderAccount = repository.getAccountState(senderAddress); AccountState senderAccount = repository.getAccountState(senderAddress);
@ -90,6 +87,7 @@ public class WorldManager {
return; return;
} }
// 1. VALIDATE THE NONCE
BigInteger nonce = senderAccount.getNonce(); BigInteger nonce = senderAccount.getNonce();
BigInteger txNonce = new BigInteger(tx.getNonce()); BigInteger txNonce = new BigInteger(tx.getNonce());
if (nonce.compareTo(txNonce) != 0) { if (nonce.compareTo(txNonce) != 0) {
@ -105,18 +103,15 @@ public class WorldManager {
// first of all debit the gas from the issuer // first of all debit the gas from the issuer
BigInteger gasDebit = tx.getTotalGasValueDebit(); BigInteger gasDebit = tx.getTotalGasValueDebit();
byte[] receiverAddress; byte[] receiverAddress;
// Contract creation or existing Contract call // Contract creation or existing Contract call
if (tx.isContractCreation()) { if (tx.isContractCreation()) {
receiverAddress = tx.getContractAddress(); receiverAddress = tx.getContractAddress();
repository.createAccount(receiverAddress); repository.createAccount(receiverAddress);
stateLogger.info("New contract created address={}", stateLogger.info("New contract created address={}",
Hex.toHexString(receiverAddress)); Hex.toHexString(receiverAddress));
} else { } else {
receiverAddress = tx.getReceiveAddress(); receiverAddress = tx.getReceiveAddress();
AccountState receiverState = repository.getAccountState(receiverAddress); AccountState receiverState = repository.getAccountState(receiverAddress);
@ -130,22 +125,19 @@ public class WorldManager {
// 2.2 UPDATE THE NONCE // 2.2 UPDATE THE NONCE
// (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION) // (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION)
BigInteger balance = senderAccount.getBalance(); repository.increaseNonce(senderAddress);
if (balance.compareTo(BigInteger.ZERO) == 1) {
repository.increaseNonce(senderAddress);
}
// actual gas value debit from the sender // actual gas value debit from the sender
// the purchase gas will be available for the // the purchase gas will be available for the
// contract in the execution state, and // contract in the execution state, and
// can be validate using GAS op // can be validate using GAS op
if (gasDebit.signum() == 1) { if (gasDebit.signum() == 1) {
BigInteger balance = senderAccount.getBalance();
if (balance.compareTo(gasDebit) == -1) { if (balance.compareTo(gasDebit) == -1) {
logger.info("No gas to start the execution: sender={}", logger.info("No gas to start the execution: sender={}",
Hex.toHexString(senderAddress)); Hex.toHexString(senderAddress));
return; return;
} }
repository.addBalance(senderAddress, gasDebit.negate()); repository.addBalance(senderAddress, gasDebit.negate());
// The coinbase get the gas cost // The coinbase get the gas cost
@ -172,7 +164,6 @@ public class WorldManager {
BigInteger senderBalance = senderAccount.getBalance(); BigInteger senderBalance = senderAccount.getBalance();
if (senderBalance.compareTo(new BigInteger(1, tx.getValue())) >= 0) { if (senderBalance.compareTo(new BigInteger(1, tx.getValue())) >= 0) {
repository.addBalance(receiverAddress, repository.addBalance(receiverAddress,
new BigInteger(1, tx.getValue())); new BigInteger(1, tx.getValue()));
repository.addBalance(senderAddress, repository.addBalance(senderAddress,
@ -242,7 +233,6 @@ public class WorldManager {
&& result.getException() instanceof Program.OutOfGasException) { && result.getException() instanceof Program.OutOfGasException) {
logger.info("contract run halted by OutOfGas: contract={}", logger.info("contract run halted by OutOfGas: contract={}",
Hex.toHexString(contractAddress)); Hex.toHexString(contractAddress));
throw result.getException(); throw result.getException();
} }
@ -262,40 +252,33 @@ public class WorldManager {
repository.addBalance(coinbase, refund.negate()); repository.addBalance(coinbase, refund.negate());
} }
if (initResults){ if (initResults) {
// Save the code created by init // Save the code created by init
byte[] bodyCode = null; byte[] bodyCode = null;
if (result.getHReturn() != null) { if (result.getHReturn() != null) {
bodyCode = result.getHReturn().array(); bodyCode = result.getHReturn().array();
} }
if (bodyCode != null) { if (bodyCode != null) {
repository.saveCode(contractAddress, bodyCode); repository.saveCode(contractAddress, bodyCode);
if (stateLogger.isInfoEnabled()) if (stateLogger.isInfoEnabled())
stateLogger stateLogger
.info("saving code of the contract to the db:\n contract={} code={}", .info("saving code of the contract to the db:\n contract={} code={}",
Hex.toHexString(contractAddress), Hex.toHexString(contractAddress),
Hex.toHexString(bodyCode)); Hex.toHexString(bodyCode));
} }
} }
// delete the marked to die accounts // delete the marked to die accounts
if (result.getDeleteAccounts() == null) return; if (result.getDeleteAccounts() == null) return;
for (DataWord address : result.getDeleteAccounts()){ for (DataWord address : result.getDeleteAccounts()){
repository.delete(address.getNoLeadZeroesData()); repository.delete(address.getNoLeadZeroesData());
} }
} }
private static BigInteger UNCLE_RATIO = BigInteger.valueOf(7).divide(BigInteger.valueOf(8));
public void applyBlock(Block block) { public void applyBlock(Block block) {
// miner reward
if (repository.getAccountState(block.getCoinbase()) == null)
repository.createAccount(block.getCoinbase());
repository.addBalance(block.getCoinbase(), Block.BLOCK_REWARD);
int i = 0; int i = 0;
List<Transaction> txList = block.getTransactionsList(); List<Transaction> txList = block.getTransactionsList();
for (Transaction tx : txList) { for (Transaction tx : txList) {
@ -304,11 +287,13 @@ public class WorldManager {
Hex.toHexString(tx.getHash())); Hex.toHexString(tx.getHash()));
++i; ++i;
} }
}
public void applyBlockList(List<Block> blocks) { // miner reward
for (int i = blocks.size() - 1; i >= 0; --i) { if (repository.getAccountState(block.getCoinbase()) == null)
applyBlock(blocks.get(i)); repository.createAccount(block.getCoinbase());
repository.addBalance(block.getCoinbase(), Block.BLOCK_REWARD);
for (Block uncle : block.getUncleList()) {
repository.addBalance(uncle.getCoinbase(), Block.BLOCK_REWARD.multiply(UNCLE_RATIO));
} }
} }

View File

@ -208,14 +208,14 @@ public class Program {
} }
} }
public void suicide(DataWord obtainer){ public void suicide(DataWord obtainer) {
// 1) pass full endowment to the obtainer // 1) pass full endowment to the obtainer
if (logger.isInfoEnabled()) if (logger.isInfoEnabled())
logger.info("Transfer to: [ {} ] heritage: [ {} ]", Hex.toHexString(obtainer.getNoLeadZeroesData()) logger.info("Transfer to: [ {} ] heritage: [ {} ]", Hex.toHexString(obtainer.getNoLeadZeroesData())
, getBalance().longValue()); , getBalance().longValue());
this.result.repository.addBalance(obtainer.getNoLeadZeroesData(), this.result.getRepository().addBalance(obtainer.getNoLeadZeroesData(),
getBalance().value()); getBalance().value());
// 2) mark the account as for delete // 2) mark the account as for delete
@ -224,8 +224,7 @@ public class Program {
public void createContract(DataWord gas, DataWord memStart, DataWord memSize) { public void createContract(DataWord gas, DataWord memStart, DataWord memSize) {
if (invokeData.byTestingSuite()){ if (invokeData.byTestingSuite()) {
logger.info("[testing suite] - omit real create"); logger.info("[testing suite] - omit real create");
return; return;
} }
@ -291,7 +290,7 @@ public class Program {
// 5. REFUND THE REMAIN GAS // 5. REFUND THE REMAIN GAS
BigInteger refundGas = gas.value().subtract(BigInteger.valueOf(result.getGasUsed())); BigInteger refundGas = gas.value().subtract(BigInteger.valueOf(result.getGasUsed()));
if (refundGas.compareTo(BigInteger.ZERO) == 1){ if (refundGas.compareTo(BigInteger.ZERO) == 1) {
this.refundGas(refundGas.intValue(), "remain gas from the internal call"); this.refundGas(refundGas.intValue(), "remain gas from the internal call");
logger.info("The remain gas refunded, account: [ {} ], gas: [ {} ] ", logger.info("The remain gas refunded, account: [ {} ], gas: [ {} ] ",
@ -341,7 +340,7 @@ public class Program {
BigInteger endowment = endowmentValue.value(); BigInteger endowment = endowmentValue.value();
BigInteger senderBalance = result.getRepository().getBalance(senderAddress); BigInteger senderBalance = result.getRepository().getBalance(senderAddress);
if (senderBalance.compareTo(endowment) < 0){ if (senderBalance.compareTo(endowment) < 0) {
stackPushZero(); stackPushZero();
return; return;
} }
@ -449,7 +448,7 @@ public class Program {
public void storageSave(byte[] key, byte[] val) { public void storageSave(byte[] key, byte[] val) {
DataWord keyWord = new DataWord(key); DataWord keyWord = new DataWord(key);
DataWord valWord = new DataWord(val); DataWord valWord = new DataWord(val);
result.repository.addStorageRow(this.programAddress, keyWord, valWord); result.getRepository().addStorageRow(this.programAddress, keyWord, valWord);
} }
public DataWord getOwnerAddress() { public DataWord getOwnerAddress() {
@ -504,7 +503,7 @@ public class Program {
} }
public DataWord storageLoad(DataWord key) { public DataWord storageLoad(DataWord key) {
return result.repository.getStorageValue(this.programAddress, key); return result.getRepository().getStorageValue(this.programAddress, key);
} }
public DataWord getPrevHash() { public DataWord getPrevHash() {

View File

@ -13,23 +13,14 @@ import java.util.Map;
public class ProgramInvokeImpl implements ProgramInvoke { public class ProgramInvokeImpl implements ProgramInvoke {
/*** TRANSACTION env ***/ /*** TRANSACTION env ***/
DataWord address; private DataWord address, origin, caller,
DataWord origin; balance, gas, gasPrice, callValue;
DataWord caller;
DataWord balance;
DataWord gas;
DataWord gasPrice;
DataWord callValue;
byte[] msgData; byte[] msgData;
/*** BLOCK env ***/ /*** BLOCK env ***/
DataWord prevHash; private DataWord prevHash, coinbase, timestamp,
DataWord coinbase; number, difficulty, gaslimit;
DataWord timestamp;
DataWord number;
DataWord difficulty;
DataWord gaslimit;
Map<DataWord, DataWord> storage; Map<DataWord, DataWord> storage;
@ -104,7 +95,6 @@ public class ProgramInvokeImpl implements ProgramInvoke {
/* ADDRESS op */ /* ADDRESS op */
public DataWord getOwnerAddress() { public DataWord getOwnerAddress() {
return address; return address;
} }

View File

@ -18,14 +18,14 @@ public class ProgramResult {
private RuntimeException exception; private RuntimeException exception;
private List<DataWord> deleteAccounts; private List<DataWord> deleteAccounts;
Repository repository = null; private Repository repository = null;
/* /*
* for testing runs , * for testing runs ,
* call/create is not executed * call/create is not executed
* but dummy recorded * but dummy recorded
*/ */
List<CallCreate> callCreateList; private List<CallCreate> callCreateList;
public void spendGas(int gas) { public void spendGas(int gas) {
gasUsed += gas; gasUsed += gas;
@ -92,11 +92,9 @@ public class ProgramResult {
return callCreateList; return callCreateList;
} }
public void addCallCreate(byte[] data, byte[] destination, byte[] gasLimit, byte[] value){ public void addCallCreate(byte[] data, byte[] destination, byte[] gasLimit, byte[] value) {
if (callCreateList == null)
if (callCreateList == null) callCreateList = new ArrayList<>();
callCreateList = new ArrayList<>(); callCreateList.add(new CallCreate(data, destination, gasLimit, value));
}
callCreateList.add(new CallCreate(data, destination, gasLimit, value));
}
} }

File diff suppressed because it is too large Load Diff