Change Repository to never accept address NOT 20 bytes

This commit is contained in:
nicksavers 2014-07-14 20:13:48 +02:00
parent db0e135278
commit b0b800f9e0
5 changed files with 82 additions and 85 deletions

View File

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

View File

@ -96,7 +96,7 @@ public class Repository {
public AccountState createAccount(byte[] addr) { public AccountState createAccount(byte[] addr) {
addr = ByteUtil.padAddressWithZeroes(addr); this.validateAddress(addr);
// 1. Save AccountState // 1. Save AccountState
AccountState state = new AccountState(); AccountState state = new AccountState();
@ -118,7 +118,7 @@ public class Repository {
public AccountState getAccountState(byte[] addr) { public AccountState getAccountState(byte[] addr) {
addr = ByteUtil.padAddressWithZeroes(addr); this.validateAddress(addr);
byte[] accountStateRLP = accountStateDB.get(addr); byte[] accountStateRLP = accountStateDB.get(addr);
@ -133,7 +133,7 @@ public class Repository {
public ContractDetails getContractDetails(byte[] addr) { public ContractDetails getContractDetails(byte[] addr) {
addr = ByteUtil.padAddressWithZeroes(addr); this.validateAddress(addr);
if (logger.isInfoEnabled()) if (logger.isInfoEnabled())
logger.info("Account: [ {} ]", Hex.toHexString(addr)); logger.info("Account: [ {} ]", Hex.toHexString(addr));
@ -152,59 +152,63 @@ public class Repository {
return details; 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){ if (state == null){
state = createAccount(address); state = createAccount(addr);
} }
BigInteger newBalance = state.addToBalance(value); BigInteger newBalance = state.addToBalance(value);
if (logger.isInfoEnabled()) if (logger.isInfoEnabled())
logger.info("Changing balance: account: [ {} ] new balance: [ {} ] delta: [ {} ]", 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; return newBalance;
} }
public BigInteger getBalance(byte[] address) { public BigInteger getBalance(byte[] addr) {
AccountState state = getAccountState(address); this.validateAddress(addr);
AccountState state = getAccountState(addr);
if (state == null) return BigInteger.ZERO; if (state == null) return BigInteger.ZERO;
return state.getBalance(); return state.getBalance();
} }
public BigInteger getNonce(byte[] address) { public BigInteger getNonce(byte[] addr) {
AccountState state = getAccountState(address); this.validateAddress(addr);
AccountState state = getAccountState(addr);
if (state == null) return BigInteger.ZERO; if (state == null) return BigInteger.ZERO;
return state.getNonce(); 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; if (state == null) return BigInteger.ZERO;
state.incrementNonce(); state.incrementNonce();
if (logger.isInfoEnabled()) if (logger.isInfoEnabled())
logger.info("Incerement nonce: account: [ {} ] new nonce: [ {} ]", 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(); 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; if (key == null) return;
address = ByteUtil.padAddressWithZeroes(address); this.validateAddress(addr);
AccountState state = getAccountState(address); AccountState state = getAccountState(addr);
ContractDetails details = getContractDetails(address); ContractDetails details = getContractDetails(addr);
if (state == null || details == null) return; if (state == null || details == null) return;
details.put(key, value); details.put(key, value);
@ -214,52 +218,52 @@ public class Repository {
if (logger.isInfoEnabled()) if (logger.isInfoEnabled())
logger.info("Storage key/value saved: account: [ {} ]\n key: [ {} ] value: [ {} ]\n new storageHash: [ {} ]", 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(key.getNoLeadZeroesData()),
Hex.toHexString(value.getNoLeadZeroesData()), Hex.toHexString(value.getNoLeadZeroesData()),
Hex.toHexString(storageHash)); Hex.toHexString(storageHash));
accountStateDB.update(address, state.getEncoded()); accountStateDB.update(addr, state.getEncoded());
contractDetailsDB.put(address, details.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; if (key == null) return null;
address = ByteUtil.padAddressWithZeroes(address); this.validateAddress(addr);
AccountState state = getAccountState(address); AccountState state = getAccountState(addr);
if (state == null) return null; if (state == null) return null;
ContractDetails details = getContractDetails(address); ContractDetails details = getContractDetails(addr);
DataWord value = details.get(key); DataWord value = details.get(key);
return value; return value;
} }
public byte[] getCode(byte[] address) { public byte[] getCode(byte[] addr) {
address = ByteUtil.padAddressWithZeroes(address); this.validateAddress(addr);
ContractDetails details = getContractDetails(address); ContractDetails details = getContractDetails(addr);
if (details == null) return null; if (details == null) return null;
return details.getCode(); return details.getCode();
} }
public void saveCode(byte[] address, byte[] code) { public void saveCode(byte[] addr, byte[] code) {
if (code == null || address == null) return; if (code == null) return;
address = ByteUtil.padAddressWithZeroes(address); this.validateAddress(addr);
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("saveCode: \n address: [ {} ], \n code: [ {} ]", logger.debug("saveCode: \n address: [ {} ], \n code: [ {} ]",
Hex.toHexString(address), Hex.toHexString(addr),
Hex.toHexString(code)); Hex.toHexString(code));
AccountState state = getAccountState(address); AccountState state = getAccountState(addr);
if (state == null) return; if (state == null) return;
ContractDetails details = getContractDetails(address); ContractDetails details = getContractDetails(addr);
details.setCode(code); details.setCode(code);
byte[] codeHash = HashUtil.sha3(code); byte[] codeHash = HashUtil.sha3(code);
@ -267,31 +271,30 @@ public class Repository {
if (logger.isInfoEnabled()) if (logger.isInfoEnabled())
logger.info("Program code saved:\n account: [ {} ]\n codeHash: [ {} ] \n code: [ {} ]", logger.info("Program code saved:\n account: [ {} ]\n codeHash: [ {} ] \n code: [ {} ]",
Hex.toHexString(address), Hex.toHexString(addr),
Hex.toHexString(codeHash), Hex.toHexString(codeHash),
Hex.toHexString(code)); Hex.toHexString(code));
accountStateDB.update(address, state.getEncoded()); accountStateDB.update(addr, state.getEncoded());
contractDetailsDB.put(address, details.getEncoded()); contractDetailsDB.put(addr, details.getEncoded());
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("saveCode: \n accountState: [ {} ], \n contractDetails: [ {} ]", logger.debug("saveCode: \n accountState: [ {} ], \n contractDetails: [ {} ]",
Hex.toHexString(state.getEncoded()), Hex.toHexString(state.getEncoded()),
Hex.toHexString(details.getEncoded())); Hex.toHexString(details.getEncoded()));
} }
public void delete(byte[] addr) {
this.validateAddress(addr);
accountStateDB.delete(addr);
contractDetailsDB.delete(addr);
}
public byte[] getRootHash() { public byte[] getRootHash() {
return this.worldState.getRootHash(); return this.worldState.getRootHash();
} }
public void delete(byte[] address){
if (address == null) return;
address = ByteUtil.padAddressWithZeroes(address);
accountStateDB.delete(address);
contractDetailsDB.delete(address);
}
public List<ByteArrayWrapper> dumpKeys(){ public List<ByteArrayWrapper> dumpKeys(){
return stateDB.dumpKeys(); return stateDB.dumpKeys();
} }
@ -361,5 +364,10 @@ public class Repository {
detailsDB.close(); 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 firstNonZero = 0;
int i = 0; int i = 0;
for (i = 0; i < data.length; ++i) { for (; i < data.length; ++i) {
if (data[i] != 0) { if (data[i] != 0) {
firstNonZero = i; firstNonZero = i;
break; break;
@ -203,16 +203,12 @@ public class ByteUtil {
return (i >= startIndex || bytes[startIndex] != 0); return (i >= startIndex || bytes[startIndex] != 0);
} }
public static byte[] padAddressWithZeroes(byte[] address){ public static byte[] padAddressWithZeroes(byte[] address){
if (address.length < 20) { if (address.length < 20) {
byte[] newAddr = new byte[20]; byte[] newAddr = new byte[20];
System.arraycopy(address, 0, newAddr, newAddr.length - address.length, address.length); System.arraycopy(address, 0, newAddr, newAddr.length - address.length, address.length);
address = newAddr; return newAddr;
return address;
} }
return address; return address;
} }
} }

View File

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

View File

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