Merge pull request #63 from nicksavers/master

Refund everything except TXFEE + DATAFEE for normal transaction
This commit is contained in:
romanman 2014-07-13 15:19:09 +03:00
commit a23a860d3f
6 changed files with 59 additions and 65 deletions

View File

@ -53,8 +53,7 @@ public class Blockchain {
private static long INITIAL_MIN_GAS_PRICE = 10 * SZABO.longValue(); private static long INITIAL_MIN_GAS_PRICE = 10 * SZABO.longValue();
private DatabaseImpl chainDb; private DatabaseImpl chainDb;
private long gasPrice = 1000;
private Block lastBlock; private Block lastBlock;
// keep the index of the chain for // keep the index of the chain for
@ -139,7 +138,6 @@ public class Blockchain {
this.index.put(block.getNumber(), block.getEncoded()); this.index.put(block.getNumber(), block.getEncoded());
WorldManager.getInstance().getWallet().processBlock(block); WorldManager.getInstance().getWallet().processBlock(block);
this.updateGasPrice(block);
this.setLastBlock(block); this.setLastBlock(block);
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("block added {}", block.toFlatString()); logger.debug("block added {}", block.toFlatString());
@ -148,13 +146,9 @@ public class Blockchain {
} }
} }
public void updateGasPrice(Block block) {
// In case of the genesis block we don't want to rely on the min gas price
this.gasPrice = block.isGenesis() ? block.getMinGasPrice() : INITIAL_MIN_GAS_PRICE;
}
public long getGasPrice() { public long getGasPrice() {
return gasPrice; // In case of the genesis block we don't want to rely on the min gas price
return lastBlock.isGenesis() ? lastBlock.getMinGasPrice() : INITIAL_MIN_GAS_PRICE;
} }
public byte[] getLatestBlockHash() { public byte[] getLatestBlockHash() {
@ -180,7 +174,6 @@ public class Blockchain {
logger.debug("Block #{} -> {}", lastBlock.getNumber(), lastBlock.toFlatString()); logger.debug("Block #{} -> {}", lastBlock.getNumber(), lastBlock.toFlatString());
} }
} }
this.updateGasPrice(lastBlock);
} finally { } finally {
// Make sure you close the iterator to avoid resource leaks. // Make sure you close the iterator to avoid resource leaks.
try { try {

View File

@ -157,7 +157,7 @@ public class Transaction {
// TODO: performance improve multiply without BigInteger // TODO: performance improve multiply without BigInteger
public BigInteger getTotalGasValueDebit() { public BigInteger getTotalGasValueDebit() {
return new BigInteger(1, gasLimit).multiply(new BigInteger(1,gasPrice)); return new BigInteger(1, gasLimit).multiply(new BigInteger(1, gasPrice));
} }
public byte[] getData() { public byte[] getData() {

View File

@ -1,16 +1,10 @@
package org.ethereum.jsontestsuite; package org.ethereum.jsontestsuite;
import org.ethereum.db.ByteArrayWrapper;
import org.ethereum.util.ByteUtil; import org.ethereum.util.ByteUtil;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import org.spongycastle.util.encoders.Hex; import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
/** /**
* www.ethereumJ.com * www.ethereumJ.com
@ -36,10 +30,10 @@ public class CallCreate {
public CallCreate(JSONObject callCreateJSON) { public CallCreate(JSONObject callCreateJSON) {
String data = (String)callCreateJSON.get("data"); String data = callCreateJSON.get("data").toString();
String destination = (String)callCreateJSON.get("destination"); String destination = callCreateJSON.get("destination").toString();
Long gasLimit = (Long)callCreateJSON.get("gasLimit"); String gasLimit = callCreateJSON.get("gasLimit").toString();
Long value = (Long)callCreateJSON.get("value"); String value = callCreateJSON.get("value").toString();
if (data != null && data.length() > 2) if (data != null && data.length() > 2)
this.data = Hex.decode(data.substring(2)); this.data = Hex.decode(data.substring(2));
@ -48,8 +42,8 @@ public class CallCreate {
this.destination = Hex.decode(destination); this.destination = Hex.decode(destination);
this.gasLimit = ByteUtil.bigIntegerToBytes( BigInteger.valueOf(gasLimit) ); this.gasLimit = ByteUtil.bigIntegerToBytes(new BigInteger(gasLimit));
this.value = ByteUtil.bigIntegerToBytes( BigInteger.valueOf(value) ); this.value = ByteUtil.bigIntegerToBytes(new BigInteger(value));
} }

View File

@ -69,8 +69,8 @@ public class Exec {
else else
this.data = new byte[0]; this.data = new byte[0];
this.gas = ByteUtil.bigIntegerToBytes( new BigInteger(gas) ); this.gas = ByteUtil.bigIntegerToBytes(new BigInteger(gas));
this.gasPrice = ByteUtil.bigIntegerToBytes( new BigInteger(gasPrice) ); this.gasPrice = ByteUtil.bigIntegerToBytes(new BigInteger(gasPrice));
this.origin = Hex.decode(origin); this.origin = Hex.decode(origin);
this.value = ByteUtil.bigIntegerToBytes(new BigInteger(value)); this.value = ByteUtil.bigIntegerToBytes(new BigInteger(value));

View File

@ -48,7 +48,6 @@ public class TestCase {
this.name = name; this.name = name;
} }
public TestCase(JSONObject testCaseJSONObj) throws ParseException{ public TestCase(JSONObject testCaseJSONObj) throws ParseException{
try { try {
@ -59,10 +58,14 @@ public class TestCase {
JSONObject postJSON = (JSONObject)testCaseJSONObj.get("post"); JSONObject postJSON = (JSONObject)testCaseJSONObj.get("post");
JSONArray callCreates = (JSONArray)testCaseJSONObj.get("callcreates"); JSONArray callCreates = (JSONArray)testCaseJSONObj.get("callcreates");
Long gasNum = (Long)testCaseJSONObj.get("gas"); String gasString = testCaseJSONObj.get("gas").toString();
this.gas = ByteUtil.bigIntegerToBytes(BigInteger.valueOf(gasNum)); this.gas = ByteUtil.bigIntegerToBytes(new BigInteger(gasString));
this.out = Helper.parseDataArray((JSONArray) testCaseJSONObj.get("out")); String outString = testCaseJSONObj.get("out").toString();
if (outString != null && outString.length() > 2)
this.out = Hex.decode(outString.substring(2));
else
this.out = new byte[0];
for (Object key : preJSON.keySet()){ for (Object key : preJSON.keySet()){

View File

@ -96,40 +96,48 @@ public class WorldManager {
return; return;
} }
// 2.1 PERFORM THE GAS VALUE TX // 3. FIND OUT THE TRANSACTION TYPE
// (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION) byte[] receiverAddress, code = null;
boolean isContractCreation = tx.isContractCreation();
// first of all debit the gas from the issuer if (isContractCreation) {
BigInteger gasDebit = tx.getTotalGasValueDebit();
byte[] receiverAddress;
// Contract creation or existing Contract call
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));
code = tx.getData(); // init code
if (logger.isInfoEnabled())
logger.info("running the init for contract: address={}",
Hex.toHexString(receiverAddress));
} else { } else {
receiverAddress = tx.getReceiveAddress(); receiverAddress = tx.getReceiveAddress();
AccountState receiverState = repository.getAccountState(receiverAddress); AccountState receiverState = repository.getAccountState(receiverAddress);
if (receiverState == null) { if (receiverState == null) {
repository.createAccount(receiverAddress); repository.createAccount(receiverAddress);
if (stateLogger.isInfoEnabled()) if (stateLogger.isInfoEnabled())
stateLogger.info("New receiver account created address={}", stateLogger.info("New receiver account created address={}",
Hex.toHexString(receiverAddress)); Hex.toHexString(receiverAddress));
} else {
code = repository.getCode(receiverAddress);
if (code != null) {
if (logger.isInfoEnabled())
logger.info("calling for existing contract: address={}",
Hex.toHexString(receiverAddress));
}
} }
} }
// 2.2 UPDATE THE NONCE // 2.1 UPDATE THE NONCE
// (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION) // (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION)
repository.increaseNonce(senderAddress); repository.increaseNonce(senderAddress);
// actual gas value debit from the sender // 2.2 PERFORM THE GAS VALUE TX
// the purchase gas will be available for the // (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION)
// contract in the execution state, and BigInteger gasDebit = tx.getTotalGasValueDebit();
// can be validate using GAS op
// Debit the actual total gas value from the sender
// the purchased gas will be available for
// the contract in the execution state,
// it can be retrieved using GAS op
if (gasDebit.signum() == 1) { if (gasDebit.signum() == 1) {
BigInteger balance = senderAccount.getBalance(); BigInteger balance = senderAccount.getBalance();
if (balance.compareTo(gasDebit) == -1) { if (balance.compareTo(gasDebit) == -1) {
@ -177,23 +185,7 @@ public class WorldManager {
} }
} }
byte[] code; // 5. CREATE OR EXECUTE PROGRAM
boolean isContractCreation = tx.isContractCreation();
// 3. FIND OUT THE TRANSACTION TYPE
if (isContractCreation) {
code = tx.getData(); // init code
if (logger.isInfoEnabled())
logger.info("running the init for contract: address={}",
Hex.toHexString(receiverAddress));
} else {
code = trackRepository.getCode(receiverAddress);
if (code != null) {
if (logger.isInfoEnabled())
logger.info("calling for existing contract: address={}",
Hex.toHexString(receiverAddress));
}
}
if (isContractCreation || code != null) { if (isContractCreation || code != null) {
Block lastBlock = blockchain.getLastBlock(); Block lastBlock = blockchain.getLastBlock();
@ -206,6 +198,18 @@ public class WorldManager {
ProgramResult result = program.getResult(); ProgramResult result = program.getResult();
applyProgramResult(result, gasDebit, trackRepository, applyProgramResult(result, gasDebit, trackRepository,
senderAddress, receiverAddress, coinbase, isContractCreation); senderAddress, receiverAddress, coinbase, isContractCreation);
} else {
// refund everything except fee (500 + 5*txdata)
BigInteger gasPrice = new BigInteger(1, tx.getGasPrice());
long dataFee = tx.getData() == null ? 0: tx.getData().length * GasCost.TXDATA;
long minTxFee = GasCost.TRANSACTION + dataFee;
BigInteger refund = gasDebit.subtract(BigInteger.valueOf(
minTxFee).multiply(gasPrice));
if (refund.signum() > 0) {
// gas refund
repository.addBalance(senderAddress, refund);
repository.addBalance(coinbase, refund.negate());
}
} }
} catch (RuntimeException e) { } catch (RuntimeException e) {
trackRepository.rollback(); trackRepository.rollback();
@ -276,7 +280,7 @@ public class WorldManager {
} }
public void applyBlock(Block block) { public void applyBlock(Block block) {
int i = 0; int i = 0;
for (Transaction tx : block.getTransactionsList()) { for (Transaction tx : block.getTransactionsList()) {
applyTransaction(tx, block.getCoinbase()); applyTransaction(tx, block.getCoinbase());