diff --git a/ethereumj-core/src/main/java/org/ethereum/core/Transaction.java b/ethereumj-core/src/main/java/org/ethereum/core/Transaction.java index 56170f25..a6a04bdc 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Transaction.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Transaction.java @@ -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() { diff --git a/ethereumj-core/src/main/java/org/ethereum/db/Repository.java b/ethereumj-core/src/main/java/org/ethereum/db/Repository.java index 35f84b37..b48c47f7 100644 --- a/ethereumj-core/src/main/java/org/ethereum/db/Repository.java +++ b/ethereumj-core/src/main/java/org/ethereum/db/Repository.java @@ -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,8 +118,8 @@ public class Repository { public AccountState getAccountState(byte[] addr) { - addr = ByteUtil.padAddressWithZeroes(addr); - + this.validateAddress(addr); + byte[] accountStateRLP = accountStateDB.get(addr); if (accountStateRLP.length == 0) { @@ -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); - - AccountState state = getAccountState(address); + this.validateAddress(addr); + + 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) { - - AccountState state = getAccountState(address); + public BigInteger increaseNonce(byte[] addr) { + + 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) { - - if (code == null || address == null) return; - address = ByteUtil.padAddressWithZeroes(address); - + public void saveCode(byte[] addr, byte[] code) { + + 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,31 +271,30 @@ 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: [ {} ]", Hex.toHexString(state.getEncoded()), Hex.toHexString(details.getEncoded())); - } + } + + public void delete(byte[] addr) { + + this.validateAddress(addr); + accountStateDB.delete(addr); + contractDetailsDB.delete(addr); + } public byte[] 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 dumpKeys(){ return stateDB.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"); + } + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/util/ByteUtil.java b/ethereumj-core/src/main/java/org/ethereum/util/ByteUtil.java index fe8b6aed..94a3b104 100644 --- a/ethereumj-core/src/main/java/org/ethereum/util/ByteUtil.java +++ b/ethereumj-core/src/main/java/org/ethereum/util/ByteUtil.java @@ -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; } } \ No newline at end of file diff --git a/ethereumj-core/src/main/java/org/ethereum/vm/DataWord.java b/ethereumj-core/src/main/java/org/ethereum/vm/DataWord.java index 6fc3b600..775c080a 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/DataWord.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/DataWord.java @@ -59,12 +59,8 @@ public class DataWord implements Comparable { 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() { diff --git a/ethereumj-core/src/main/java/org/ethereum/vm/Program.java b/ethereumj-core/src/main/java/org/ethereum/vm/Program.java index 3be83ec8..10f388c4 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/Program.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/Program.java @@ -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;