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 DatabaseImpl chainDb;
private long gasPrice = 1000;
private Block lastBlock;
// keep the index of the chain for
@ -139,7 +138,6 @@ public class Blockchain {
this.index.put(block.getNumber(), block.getEncoded());
WorldManager.getInstance().getWallet().processBlock(block);
this.updateGasPrice(block);
this.setLastBlock(block);
if (logger.isDebugEnabled())
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() {
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() {
@ -180,7 +174,6 @@ public class Blockchain {
logger.debug("Block #{} -> {}", lastBlock.getNumber(), lastBlock.toFlatString());
}
}
this.updateGasPrice(lastBlock);
} finally {
// Make sure you close the iterator to avoid resource leaks.
try {

View File

@ -157,7 +157,7 @@ public class Transaction {
// TODO: performance improve multiply without BigInteger
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() {

View File

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

View File

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

View File

@ -48,7 +48,6 @@ public class TestCase {
this.name = name;
}
public TestCase(JSONObject testCaseJSONObj) throws ParseException{
try {
@ -59,10 +58,14 @@ public class TestCase {
JSONObject postJSON = (JSONObject)testCaseJSONObj.get("post");
JSONArray callCreates = (JSONArray)testCaseJSONObj.get("callcreates");
Long gasNum = (Long)testCaseJSONObj.get("gas");
this.gas = ByteUtil.bigIntegerToBytes(BigInteger.valueOf(gasNum));
this.out = Helper.parseDataArray((JSONArray) testCaseJSONObj.get("out"));
String gasString = testCaseJSONObj.get("gas").toString();
this.gas = ByteUtil.bigIntegerToBytes(new BigInteger(gasString));
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()){

View File

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