Merge pull request #69 from nicksavers/master
Change Repository to never accept address NOT 20 bytes
This commit is contained in:
commit
a659787a8f
|
@ -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() {
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue