Contract Creation:

+ main sequence
 - no edge cases testeds
This commit is contained in:
romanman 2014-06-07 19:08:50 +01:00
parent 36a8c2da62
commit bf6693122d
5 changed files with 89 additions and 31 deletions

View File

@ -1,11 +1,14 @@
package org.ethereum.manager;
import io.netty.channel.AddressedEnvelope;
import org.ethereum.core.AccountState;
import org.ethereum.core.Block;
import org.ethereum.core.Transaction;
import org.ethereum.crypto.HashUtil;
import org.ethereum.db.Database;
import org.ethereum.trie.Trie;
import org.ethereum.vm.Program;
import org.ethereum.vm.ProgramResult;
import org.ethereum.vm.VM;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -64,19 +67,23 @@ public class WorldManager {
return;
}
// 2. THE SIMPLE BALANCE CHANGE SHOULD HAPPEN ANYWAY
AccountState recieverState = null;
// 2. FIND OUT WHAT IS THE TRANSACTION TYPE
// Check if the receive is a new contract
if (tx.isContractCreation()){
// todo 0. run the init method
byte[] contractAddress= tx.getContractAddress();
AccountState contractAccount = new AccountState(BigInteger.ZERO, BigInteger.valueOf(0));
allAccountsState.update(contractAddress, contractAccount.getEncoded());
recieverState = contractAccount;
stateLogger.info("New contract created address={}",
Hex.toHexString(contractAddress));
}
VM vm = new VM();
Program program = new Program(null, null);
} else{
AccountState recieverState;
// if reciver was not set by
// creation of contract
if (recieverState == null) {
byte[] accountData = this.allAccountsState.get(tx.getReceiveAddress());
if (accountData.length == 0){
@ -90,15 +97,11 @@ public class WorldManager {
stateLogger.info("Account updated address={}",
Hex.toHexString(tx.getReceiveAddress()));
}
}
// APPLY THE BALANCE VALUE
recieverState.addToBalance(new BigInteger(1, tx.getValue()));
senderState.addToBalance(new BigInteger(1, tx.getValue()).negate());
// todo 2. check if the address is a contract, if it is perform contract call
if (senderState.getBalance().compareTo(BigInteger.ZERO) == 1){
senderState.incrementNonce();
@ -106,6 +109,36 @@ public class WorldManager {
allAccountsState.update(tx.getReceiveAddress(), recieverState.getEncoded());
}
// 3. FIND OUT WHAT IS THE TRANSACTION TYPE
if (tx.isContractCreation()){
byte[] initCode = tx.getData();
VM vm = new VM();
Program program = new Program(initCode, null);
vm.play(program);
ProgramResult result = program.getResult();
byte[] bodyCode = result.gethReturn().array();
// todo: what if the body code is null , still submit ?
// TODO: (!!!!!) ALL THE CHECKS FOR THE PROGRAM RESULT
byte[] key = HashUtil.sha3(bodyCode);
chainDB.put(key, bodyCode);
if (stateLogger.isInfoEnabled())
stateLogger.info("saving code of the contract to the db: sha3(code)={} code={}",
Hex.toHexString(key),
Hex.toHexString(bodyCode));
} else{
// todo 2. check if the address is a contract, if it is perform contract call
}
pendingTransactions.put(Hex.toHexString(tx.getHash()), tx);

View File

@ -24,7 +24,7 @@ public class Program {
Map<DataWord, DataWord> storage = new HashMap<DataWord, DataWord>();
ByteBuffer memory = null;
ByteBuffer hReturn = null;
ProgramResult result = new ProgramResult();
byte[] ops;
int pc = 0;
@ -84,7 +84,7 @@ public class Program {
}
public void setHReturn(ByteBuffer buff){
hReturn = buff;
result.setHReturn(buff.array());
}
public void step(){
@ -267,6 +267,14 @@ public class Program {
}
public ProgramResult getResult() {
return result;
}
public void setRuntimeFailure(RuntimeException e){
result.setException(e);
}
public void fullTrace(){
// todo: add gas to full trace calc
@ -336,8 +344,8 @@ public class Program {
global.append(" -- MEMORY -- ").append(memoryData).append("\n");
global.append(" -- STORAGE -- ").append(storageData).append("\n");
if (hReturn != null){
global.append("\n HReturn: ").append(Hex.toHexString(hReturn.array()));
if (result.gethReturn() != null){
global.append("\n HReturn: ").append(Hex.toHexString(result.gethReturn().array()));
}
if (listener != null){

View File

@ -12,6 +12,7 @@ public class ProgramResult {
private int gasUsed = 0;
private ByteBuffer hReturn = null;
private RuntimeException exception;
public void spendGas(int gas){
gasUsed += gas;
@ -23,5 +24,17 @@ public class ProgramResult {
this.hReturn.put(hReturn);
}
public ByteBuffer gethReturn() {
return hReturn;
}
public RuntimeException getException() {
return exception;
}
public void setException(RuntimeException exception) {
this.exception = exception;
}
}

View File

@ -556,7 +556,7 @@ public class VM {
DataWord size = program.stackPop();
ByteBuffer hReturn = program.memoryChunk(offset, size);
program.hReturn = hReturn;
program.setHReturn(hReturn);
program.step();
program.stop();
@ -585,8 +585,12 @@ public class VM {
public void play(Program program){
try {
while(!program.isStopped())
this.step(program);
} catch (RuntimeException e) {
program.setRuntimeFailure(e);
}
}

View File

@ -2141,7 +2141,7 @@ public class VMTest {
vm.step(program);
vm.step(program);
assertEquals(s_expected_1, Hex.toHexString(program.hReturn.array()).toUpperCase());
assertEquals(s_expected_1, Hex.toHexString(program.getResult().gethReturn().array()).toUpperCase());
assertTrue(program.stopped);
}
@ -2160,7 +2160,7 @@ public class VMTest {
vm.step(program);
vm.step(program);
assertEquals(s_expected_1, Hex.toHexString(program.hReturn.array()).toUpperCase());
assertEquals(s_expected_1, Hex.toHexString(program.getResult().gethReturn().array()).toUpperCase());
assertTrue(program.stopped);
}
@ -2180,7 +2180,7 @@ public class VMTest {
vm.step(program);
vm.step(program);
assertEquals(s_expected_1, Hex.toHexString(program.hReturn.array()).toUpperCase());
assertEquals(s_expected_1, Hex.toHexString(program.getResult().gethReturn().array()).toUpperCase());
assertTrue(program.stopped);
}
@ -2201,7 +2201,7 @@ public class VMTest {
vm.step(program);
vm.step(program);
assertEquals(s_expected_1, Hex.toHexString(program.hReturn.array()).toUpperCase());
assertEquals(s_expected_1, Hex.toHexString(program.getResult().gethReturn().array()).toUpperCase());
assertTrue(program.stopped);
}