Contract execution:
+ apply results encapsulated + OutOfGas added to step spend + Program GAS call bug fixed
This commit is contained in:
parent
11e9190957
commit
33af300619
|
@ -133,18 +133,79 @@ public class WorldManager {
|
|||
VM vm = new VM();
|
||||
Program program = new Program(initCode, programInvoke);
|
||||
vm.play(program);
|
||||
ProgramResult result = program.getResult();
|
||||
applyProgramResult(result, gasDebit, senderState, receiverState, senderAddress, tx.getContractAddress());
|
||||
|
||||
} else {
|
||||
|
||||
if (receiverState.getCodeHash() != HashUtil.EMPTY_DATA_HASH){
|
||||
|
||||
byte[] programCode = chainDB.get(receiverState.getCodeHash());
|
||||
if (programCode != null && programCode.length != 0){
|
||||
|
||||
Block lastBlock =
|
||||
MainData.instance.getBlockchain().getLastBlock();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info("calling for existing contract: addres={}" , Hex.toHexString(tx.getReceiveAddress()));
|
||||
|
||||
// first of all debit the gas from the issuer
|
||||
BigInteger gasDebit = tx.getTotalGasDebit();
|
||||
senderState.addToBalance(gasDebit.negate());
|
||||
if (senderState.getBalance().signum() == -1){
|
||||
// todo: the sender can't afford this contract do Out-Of-Gas
|
||||
}
|
||||
|
||||
if(stateLogger.isInfoEnabled())
|
||||
stateLogger.info("Before contract execution the sender address debit with gas total cost, \n sender={} \n contract={} \n gas_debit= {}",
|
||||
Hex.toHexString( tx.getSender() ), Hex.toHexString(tx.getReceiveAddress()), gasDebit);
|
||||
worldState.update(senderAddress, senderState.getEncoded());
|
||||
|
||||
// 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);
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
pendingTransactions.put(Hex.toHexString(tx.getHash()), tx);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* After any contract code finish the run
|
||||
* the certain result should take place,
|
||||
* according the given circumstances
|
||||
*
|
||||
* @param result
|
||||
* @param gasDebit
|
||||
* @param senderState
|
||||
* @param receiverState
|
||||
* @param senderAddress
|
||||
* @param contractAddress
|
||||
*/
|
||||
private void applyProgramResult(ProgramResult result, BigInteger gasDebit,
|
||||
AccountState senderState, AccountState receiverState,
|
||||
byte[] senderAddress, byte[] contractAddress) {
|
||||
|
||||
// TODO: (!!!!!) ALL THE CHECKS FOR THE PROGRAM RESULT
|
||||
// TODO: (!!!!!) consider introduce one method for applying results
|
||||
if (result.getException() != null &&
|
||||
result.getException() instanceof Program.OutOfGasException){
|
||||
|
||||
// The out of gas means nothing applied
|
||||
// todo: find out what exactly should be reverted in that case
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Save the code created by init
|
||||
byte[] bodyCode = null;
|
||||
if (result.gethReturn() != null){
|
||||
|
@ -160,7 +221,7 @@ public class WorldManager {
|
|||
if (refund.signum() > 0){
|
||||
if(stateLogger.isInfoEnabled())
|
||||
stateLogger.info("After contract execution the sender address refunded with gas leftover , \n sender={} \n contract={} \n gas_refund= {}",
|
||||
Hex.toHexString(tx.getSender()) ,Hex.toHexString(tx.getContractAddress()), refund);
|
||||
Hex.toHexString(senderAddress) ,Hex.toHexString(contractAddress), refund);
|
||||
senderState.addToBalance(refund);
|
||||
worldState.update(senderAddress, senderState.getEncoded());
|
||||
}
|
||||
|
@ -169,11 +230,11 @@ public class WorldManager {
|
|||
byte[] codeKey = HashUtil.sha3(bodyCode);
|
||||
chainDB.put(codeKey, bodyCode);
|
||||
receiverState.setCodeHash(codeKey);
|
||||
worldState.update(tx.getContractAddress(), receiverState.getEncoded());
|
||||
worldState.update(contractAddress, receiverState.getEncoded());
|
||||
|
||||
if (stateLogger.isInfoEnabled())
|
||||
stateLogger.info("saving code of the contract to the db:\n contract={} sha3(code)={} code={}",
|
||||
Hex.toHexString(tx.getContractAddress()),
|
||||
Hex.toHexString(contractAddress),
|
||||
Hex.toHexString(codeKey),
|
||||
Hex.toHexString(bodyCode));
|
||||
}
|
||||
|
@ -182,49 +243,8 @@ public class WorldManager {
|
|||
Map<DataWord, DataWord> storage = result.getStorage();
|
||||
if (storage != null){
|
||||
ContractDetails contractDetails = new ContractDetails(storage);
|
||||
detaildDB.put(tx.getContractAddress() , contractDetails.getEncoded());
|
||||
detaildDB.put(contractAddress , contractDetails.getEncoded());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
if (receiverState.getCodeHash() != HashUtil.EMPTY_DATA_HASH){
|
||||
|
||||
byte[] programCode = chainDB.get(receiverState.getCodeHash());
|
||||
if (programCode != null && programCode.length != 0){
|
||||
|
||||
Block lastBlock =
|
||||
MainData.instance.getBlockchain().getLastBlock();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
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);
|
||||
|
||||
VM vm = new VM();
|
||||
Program program = new Program(programCode, programInvoke);
|
||||
vm.play(program);
|
||||
|
||||
ProgramResult result = program.getResult();
|
||||
|
||||
// TODO: (!!!!!) ALL THE CHECKS FOR THE PROGRAM RESULT
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pendingTransactions.put(Hex.toHexString(tx.getHash()), tx);
|
||||
}
|
||||
|
||||
public void applyTransactionList(List<Transaction> txList) {
|
||||
|
|
|
@ -61,6 +61,9 @@ public class DataWord {
|
|||
public int intValue(){
|
||||
return new BigInteger(1, data).intValue();
|
||||
}
|
||||
public long longValue(){
|
||||
return new BigInteger(1, data).longValue();
|
||||
}
|
||||
|
||||
public BigInteger sValue(){
|
||||
return new BigInteger(data);
|
||||
|
|
|
@ -173,7 +173,6 @@ public class Program {
|
|||
return ByteBuffer.wrap(chunk);
|
||||
}
|
||||
|
||||
|
||||
private void allocateMemory(int address, byte[] value){
|
||||
|
||||
int memSize = 0;
|
||||
|
@ -216,8 +215,11 @@ public class Program {
|
|||
|
||||
|
||||
public void spendGas(int gasValue){
|
||||
// todo: check it against avail gas
|
||||
// todo: out of gas will revert the changes [YP 5, 6 ]
|
||||
|
||||
long afterSpend = invokeData.getGas().longValue() - gasValue - result.getGasUsed();
|
||||
if (afterSpend < 0)
|
||||
throw new OutOfGasException();
|
||||
|
||||
result.spendGas(gasValue);
|
||||
}
|
||||
|
||||
|
@ -257,8 +259,11 @@ public class Program {
|
|||
}
|
||||
|
||||
public DataWord getGas(){
|
||||
|
||||
if (invokeData == null) return new DataWord( new byte[0]);
|
||||
return invokeData.getGas();
|
||||
|
||||
long afterSpend = invokeData.getGas().longValue() - result.getGasUsed();
|
||||
return new DataWord(afterSpend);
|
||||
}
|
||||
|
||||
|
||||
|
@ -401,18 +406,14 @@ public class Program {
|
|||
if (!Arrays.equals(txData, ops)){
|
||||
globalOutput.append("\n msg.data: ").append(Hex.toHexString( txData ));
|
||||
}
|
||||
|
||||
globalOutput.append("\n\n Spent Gas: ").append(result.getGasUsed());
|
||||
|
||||
|
||||
if (listener != null){
|
||||
listener.output(globalOutput.toString());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void addListener(ProgramListener listener){
|
||||
this.listener = listener;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue