Merge pull request #69 from nicksavers/master

Change Repository to never accept address NOT 20 bytes
This commit is contained in:
romanman 2014-07-14 21:27:40 +03:00
commit a659787a8f
5 changed files with 82 additions and 85 deletions

View File

@ -173,10 +173,7 @@ public class Transaction {
public byte[] getContractAddress() {
if (!isContractCreation()) return null;
byte[] encSender = RLP.encodeElement(getSender());
byte[] encNonce = RLP.encodeElement(nonce);
return HashUtil.sha3omit12(RLP.encodeList(encSender, encNonce));
return HashUtil.calcNewAddr(this.getSender(), this.getNonce());
}
public boolean isContractCreation() {

View File

@ -96,7 +96,7 @@ public class Repository {
public AccountState createAccount(byte[] addr) {
addr = ByteUtil.padAddressWithZeroes(addr);
this.validateAddress(addr);
// 1. Save AccountState
AccountState state = new AccountState();
@ -118,7 +118,7 @@ public class Repository {
public AccountState getAccountState(byte[] addr) {
addr = ByteUtil.padAddressWithZeroes(addr);
this.validateAddress(addr);
byte[] accountStateRLP = accountStateDB.get(addr);
@ -133,7 +133,7 @@ public class Repository {
public ContractDetails getContractDetails(byte[] addr) {
addr = ByteUtil.padAddressWithZeroes(addr);
this.validateAddress(addr);
if (logger.isInfoEnabled())
logger.info("Account: [ {} ]", Hex.toHexString(addr));
@ -152,59 +152,63 @@ public class Repository {
return details;
}
public BigInteger addBalance(byte[] address, BigInteger value) {
public BigInteger addBalance(byte[] addr, BigInteger value) {
address = ByteUtil.padAddressWithZeroes(address);
this.validateAddress(addr);
AccountState state = getAccountState(address);
AccountState state = getAccountState(addr);
if (state == null){
state = createAccount(address);
state = createAccount(addr);
}
BigInteger newBalance = state.addToBalance(value);
if (logger.isInfoEnabled())
logger.info("Changing balance: account: [ {} ] new balance: [ {} ] delta: [ {} ]",
Hex.toHexString(address), newBalance.toString(), value);
Hex.toHexString(addr), newBalance.toString(), value);
accountStateDB.update(address, state.getEncoded());
accountStateDB.update(addr, state.getEncoded());
return newBalance;
}
public BigInteger getBalance(byte[] address) {
AccountState state = getAccountState(address);
public BigInteger getBalance(byte[] addr) {
this.validateAddress(addr);
AccountState state = getAccountState(addr);
if (state == null) return BigInteger.ZERO;
return state.getBalance();
}
public BigInteger getNonce(byte[] address) {
AccountState state = getAccountState(address);
public BigInteger getNonce(byte[] addr) {
this.validateAddress(addr);
AccountState state = getAccountState(addr);
if (state == null) return BigInteger.ZERO;
return state.getNonce();
}
public BigInteger increaseNonce(byte[] address) {
public BigInteger increaseNonce(byte[] addr) {
AccountState state = getAccountState(address);
this.validateAddress(addr);
AccountState state = getAccountState(addr);
if (state == null) return BigInteger.ZERO;
state.incrementNonce();
if (logger.isInfoEnabled())
logger.info("Incerement nonce: account: [ {} ] new nonce: [ {} ]",
Hex.toHexString(address), state.getNonce().longValue());
Hex.toHexString(addr), state.getNonce().longValue());
accountStateDB.update(address, state.getEncoded());
accountStateDB.update(addr, state.getEncoded());
return state.getNonce();
}
public void addStorageRow(byte[] address, DataWord key, DataWord value) {
public void addStorageRow(byte[] addr, DataWord key, DataWord value) {
if (address == null || key == null) return;
address = ByteUtil.padAddressWithZeroes(address);
if (key == null) return;
this.validateAddress(addr);
AccountState state = getAccountState(address);
ContractDetails details = getContractDetails(address);
AccountState state = getAccountState(addr);
ContractDetails details = getContractDetails(addr);
if (state == null || details == null) return;
details.put(key, value);
@ -214,52 +218,52 @@ public class Repository {
if (logger.isInfoEnabled())
logger.info("Storage key/value saved: account: [ {} ]\n key: [ {} ] value: [ {} ]\n new storageHash: [ {} ]",
Hex.toHexString(address),
Hex.toHexString(addr),
Hex.toHexString(key.getNoLeadZeroesData()),
Hex.toHexString(value.getNoLeadZeroesData()),
Hex.toHexString(storageHash));
accountStateDB.update(address, state.getEncoded());
contractDetailsDB.put(address, details.getEncoded());
accountStateDB.update(addr, state.getEncoded());
contractDetailsDB.put(addr, details.getEncoded());
}
public DataWord getStorageValue(byte[] address, DataWord key) {
public DataWord getStorageValue(byte[] addr, DataWord key) {
if (key == null || address == null) return null;
address = ByteUtil.padAddressWithZeroes(address);
if (key == null) return null;
this.validateAddress(addr);
AccountState state = getAccountState(address);
AccountState state = getAccountState(addr);
if (state == null) return null;
ContractDetails details = getContractDetails(address);
ContractDetails details = getContractDetails(addr);
DataWord value = details.get(key);
return value;
}
public byte[] getCode(byte[] address) {
public byte[] getCode(byte[] addr) {
address = ByteUtil.padAddressWithZeroes(address);
ContractDetails details = getContractDetails(address);
this.validateAddress(addr);
ContractDetails details = getContractDetails(addr);
if (details == null) return null;
return details.getCode();
}
public void saveCode(byte[] address, byte[] code) {
public void saveCode(byte[] addr, byte[] code) {
if (code == null || address == null) return;
address = ByteUtil.padAddressWithZeroes(address);
if (code == null) return;
this.validateAddress(addr);
if (logger.isDebugEnabled())
logger.debug("saveCode: \n address: [ {} ], \n code: [ {} ]",
Hex.toHexString(address),
Hex.toHexString(addr),
Hex.toHexString(code));
AccountState state = getAccountState(address);
AccountState state = getAccountState(addr);
if (state == null) return;
ContractDetails details = getContractDetails(address);
ContractDetails details = getContractDetails(addr);
details.setCode(code);
byte[] codeHash = HashUtil.sha3(code);
@ -267,12 +271,12 @@ public class Repository {
if (logger.isInfoEnabled())
logger.info("Program code saved:\n account: [ {} ]\n codeHash: [ {} ] \n code: [ {} ]",
Hex.toHexString(address),
Hex.toHexString(addr),
Hex.toHexString(codeHash),
Hex.toHexString(code));
accountStateDB.update(address, state.getEncoded());
contractDetailsDB.put(address, details.getEncoded());
accountStateDB.update(addr, state.getEncoded());
contractDetailsDB.put(addr, details.getEncoded());
if (logger.isDebugEnabled())
logger.debug("saveCode: \n accountState: [ {} ], \n contractDetails: [ {} ]",
@ -280,16 +284,15 @@ public class Repository {
Hex.toHexString(details.getEncoded()));
}
public byte[] getRootHash() {
return this.worldState.getRootHash();
public void delete(byte[] addr) {
this.validateAddress(addr);
accountStateDB.delete(addr);
contractDetailsDB.delete(addr);
}
public void delete(byte[] address){
if (address == null) return;
address = ByteUtil.padAddressWithZeroes(address);
accountStateDB.delete(address);
contractDetailsDB.delete(address);
public byte[] getRootHash() {
return this.worldState.getRootHash();
}
public List<ByteArrayWrapper> dumpKeys(){
@ -361,5 +364,10 @@ public class Repository {
detailsDB.close();
}
private void validateAddress(byte[] addr) {
if (addr == null || addr.length < 20) {
logger.error("Can't create address {} because is null or length != 20", ByteUtil.toHexString(addr));
throw new IllegalArgumentException("Address must be a byte-array of length 20");
}
}
}

View File

@ -171,7 +171,7 @@ public class ByteUtil {
int firstNonZero = 0;
int i = 0;
for (i = 0; i < data.length; ++i) {
for (; i < data.length; ++i) {
if (data[i] != 0) {
firstNonZero = i;
break;
@ -203,16 +203,12 @@ public class ByteUtil {
return (i >= startIndex || bytes[startIndex] != 0);
}
public static byte[] padAddressWithZeroes(byte[] address){
if (address.length < 20) {
byte[] newAddr = new byte[20];
System.arraycopy(address, 0, newAddr, newAddr.length - address.length, address.length);
address = newAddr;
return address;
return newAddr;
}
return address;
}
}

View File

@ -59,12 +59,8 @@ public class DataWord implements Comparable<DataWord> {
public byte[] getNoLeadZeroesData() {
return ByteUtil.stripLeadingZeroes(data);
}
public byte[] get20LastBytes(){
byte[] last20bytes = new byte[20];
System.arraycopy(this.data, 12, last20bytes, 0, 20);
return last20bytes;
public byte[] getAddress() {
return Arrays.copyOfRange(data, 12, data.length);
}
public BigInteger value() {

View File

@ -47,7 +47,7 @@ public class Program {
this.invokeData = invokeData;
this.ops = ops;
this.programAddress = invokeData.getOwnerAddress().getNoLeadZeroesData();
this.programAddress = invokeData.getOwnerAddress().getAddress();
}
public byte getCurrentOp() {
@ -217,14 +217,14 @@ public class Program {
DataWord balance = getBalance(this.getOwnerAddress());
// 1) pass full endowment to the obtainer
if (logger.isInfoEnabled())
logger.info("Transfer to: [ {} ] heritage: [ {} ]", Hex.toHexString(obtainer.getNoLeadZeroesData())
logger.info("Transfer to: [ {} ] heritage: [ {} ]", Hex.toHexString(obtainer.getAddress())
, balance.longValue());
this.result.getRepository().addBalance(obtainer.getNoLeadZeroesData(), balance.value());
this.result.getRepository().addBalance(getOwnerAddress().getNoLeadZeroesData(), balance.value().negate());
this.result.getRepository().addBalance(obtainer.getAddress(), balance.value());
this.result.getRepository().addBalance(this.getOwnerAddress().getAddress(), balance.value().negate());
// 2) mark the account as for delete
result.addDeleteAccount(getOwnerAddress());
result.addDeleteAccount(this.getOwnerAddress());
}
public void createContract(DataWord value, DataWord memStart, DataWord memSize) {
@ -237,7 +237,7 @@ public class Program {
// [1] FETCH THE CODE FROM THE MEMORY
ByteBuffer programCode = memoryChunk(memStart, memSize);
byte[] senderAddress = this.getOwnerAddress().getNoLeadZeroesData();
byte[] senderAddress = this.getOwnerAddress().getAddress();
if (logger.isInfoEnabled())
logger.info("creating a new contract inside contract run: [{}]", Hex.toHexString(senderAddress));
@ -247,7 +247,7 @@ public class Program {
// [2] CREATE THE CONTRACT ADDRESS
byte[] nonce = result.getRepository().getNonce(senderAddress).toByteArray();
byte[] newAddress = HashUtil.calcNewAddr(this.getOwnerAddress().getNoLeadZeroesData(), nonce);
byte[] newAddress = HashUtil.calcNewAddr(this.getOwnerAddress().getAddress(), nonce);
result.getRepository().createAccount(newAddress);
// [3] UPDATE THE NONCE
@ -303,7 +303,7 @@ public class Program {
if (logger.isInfoEnabled()){
logger.info("The remain gas refunded, account: [ {} ], gas: [ {} ] ",
Hex.toHexString(this.getOwnerAddress().getNoLeadZeroesData()),
Hex.toHexString(this.getOwnerAddress().getAddress()),
refundGas);
}
}
@ -327,7 +327,7 @@ public class Program {
ByteBuffer data = memoryChunk(inDataOffs, inDataSize);
// FETCH THE SAVED STORAGE
byte[] toAddress = toAddressDW.getNoLeadZeroesData();
byte[] toAddress = toAddressDW.getAddress();
// FETCH THE CODE
byte[] programCode = this.result.getRepository().getCode(toAddress);
@ -336,7 +336,7 @@ public class Program {
logger.info("calling for existing contract: address={}",
Hex.toHexString(toAddress));
byte[] senderAddress = this.getOwnerAddress().getNoLeadZeroesData();
byte[] senderAddress = this.getOwnerAddress().getAddress();
// 2.1 PERFORM THE GAS VALUE TX
// (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION)
@ -362,7 +362,7 @@ public class Program {
stackPushOne();
this.getResult().addCallCreate(data.array(),
toAddressDW.getNoLeadZeroesData(),
toAddressDW.getAddress(),
gas.getNoLeadZeroesData(), endowmentValue.getNoLeadZeroesData());
return;
@ -469,7 +469,7 @@ public class Program {
public DataWord getBalance(DataWord address) {
if (invokeData == null) return new DataWord( new byte[0]);
BigInteger balance = result.getRepository().getBalance(address.getNoLeadZeroesData());
BigInteger balance = result.getRepository().getBalance(address.getAddress());
DataWord balanceData = new DataWord(balance.toByteArray());
return balanceData;