Skip to content
This repository has been archived by the owner on Dec 5, 2024. It is now read-only.

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
mkalinin committed Jan 7, 2019
2 parents e5ed70b + b7d13a2 commit 304b166
Show file tree
Hide file tree
Showing 30 changed files with 667 additions and 376 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ public MainNetConfig() {
add(2_463_000, new Eip150HFConfig(new DaoHFConfig()));
add(2_675_000, new Eip160HFConfig(new DaoHFConfig()));
add(4_370_000, new ByzantiumConfig(new DaoHFConfig()));
add(7_080_000, new ConstantinopleConfig(new DaoHFConfig()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -289,19 +289,24 @@ private void create() {
m_endGas = m_endGas.subtract(BigInteger.valueOf(basicTxCost));
result.spendGas(basicTxCost);
} else {
Repository originalRepo = track;
// Some TCK tests have storage only addresses (no code, zero nonce etc) - impossible situation in the real network
// So, we should clean up it before reuse, but as tx not always goes successful, state should be correctly
// reverted in that case too
if (cacheTrack.hasContractDetails(newContractAddress)) {
originalRepo = track.clone();
originalRepo.delete(newContractAddress);
}
ProgramInvoke programInvoke = programInvokeFactory.createProgramInvoke(tx, currentBlock,
cacheTrack, track, blockStore);
cacheTrack, originalRepo, blockStore);

this.vm = new VM(config, vmHook);
this.program = new Program(tx.getData(), programInvoke, tx, config, vmHook).withCommonConfig(commonConfig);

// reset storage if the contract with the same address already exists
// TCK test case only - normally this is near-impossible situation in the real network
// TODO make via Trie.clear() without keyset
// ContractDetails contractDetails = program.getStorage().getContractDetails(newContractAddress);
// for (DataWord key : contractDetails.getStorageKeys()) {
// program.storageSave(key, DataWord.ZERO);
// }
ContractDetails contractDetails = program.getStorage().getContractDetails(newContractAddress);
contractDetails.deleteStorage();
}

BigInteger endowment = toBI(tx.getValue());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ public interface ContractDetails {

Set<DataWord> getStorageKeys();

// Removes all storage, key by key, if supported
void deleteStorage();

Map<DataWord,DataWord> getStorage(@Nullable Collection<DataWord> keys);

Map<DataWord, DataWord> getStorage();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,11 @@ public Set<DataWord> getStorageKeys() {
throw new RuntimeException("Not supported");
}

@Override
public void deleteStorage() {
// do nothing as getStorageKeys() is not supported
}

@Override
public Map<DataWord, DataWord> getStorage(@Nullable Collection<DataWord> keys) {
throw new RuntimeException("Not supported");
Expand Down
168 changes: 65 additions & 103 deletions ethereumj-core/src/main/java/org/ethereum/solidity/SolidityType.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import static org.ethereum.util.ByteUtil.toHexString;

public abstract class SolidityType {
private final static int Int32Size = 32;
protected String name;

public SolidityType(String name) {
Expand All @@ -56,7 +57,7 @@ public String getCanonicalName() {

@JsonCreator
public static SolidityType getType(String typeName) {
if (typeName.contains("[")) return ArrayType.getType(typeName);
if (typeName.endsWith("]")) return ArrayType.getType(typeName);
if ("bool".equals(typeName)) return new BoolType();
if (typeName.startsWith("int")) return new IntType(typeName);
if (typeName.startsWith("uint")) return new UnsignedIntType(typeName);
Expand Down Expand Up @@ -86,7 +87,7 @@ public Object decode(byte[] encoded) {
* which is effectively the int offset to dynamic data
*/
public int getFixedSize() {
return 32;
return Int32Size;
}

public boolean isDynamicType() {
Expand All @@ -101,8 +102,8 @@ public String toString() {

public static abstract class ArrayType extends SolidityType {
public static ArrayType getType(String typeName) {
int idx1 = typeName.indexOf("[");
int idx2 = typeName.indexOf("]", idx1);
int idx1 = typeName.lastIndexOf("[");
int idx2 = typeName.lastIndexOf("]");
if (idx1 + 1 == idx2) {
return new DynamicArrayType(typeName);
} else {
Expand All @@ -114,11 +115,7 @@ public static ArrayType getType(String typeName) {

public ArrayType(String name) {
super(name);
int idx = name.indexOf("[");
String st = name.substring(0, idx);
int idx2 = name.indexOf("]", idx);
String subDim = idx2 + 1 == name.length() ? "" : name.substring(idx2 + 1);
elementType = SolidityType.getType(st + subDim);
elementType = SolidityType.getType(name.substring(0, name.lastIndexOf("[")));
}

@Override
Expand All @@ -135,23 +132,42 @@ public byte[] encode(Object value) {
throw new RuntimeException("List value expected for type " + getName());
}
}

@Override
public String getCanonicalName() {
return getArrayCanonicalName("");
}

String getArrayCanonicalName(String parentDimStr) {
String myDimStr = parentDimStr + getCanonicalDimension();
if (getElementType() instanceof ArrayType) {
return ((ArrayType) getElementType()).
getArrayCanonicalName(myDimStr);
protected byte[] encodeTuple(List l) {
byte[][] elems;
if (elementType.isDynamicType()) {
elems = new byte[l.size() * 2][];
int offset = l.size() * Int32Size;
for (int i = 0; i < l.size(); i++) {
elems[i] = IntType.encodeInt(offset);
byte[] encoded = elementType.encode(l.get(i));
elems[l.size() + i] = encoded;
offset += Int32Size * ((encoded.length - 1) / Int32Size + 1);
}
} else {
return getElementType().getCanonicalName() + myDimStr;
elems = new byte[l.size()][];
for (int i = 0; i < l.size(); i++) {
elems[i] = elementType.encode(l.get(i));
}
}
return ByteUtil.merge(elems);
}

public Object[] decodeTuple(byte[] encoded, int origOffset, int len) {
int offset = origOffset;
Object[] ret = new Object[len];

for (int i = 0; i < len; i++) {
if (elementType.isDynamicType()) {
ret[i] = elementType.decode(encoded, origOffset + IntType.decodeInt(encoded, offset).intValue());
} else {
ret[i] = elementType.decode(encoded, offset);
}
offset += elementType.getFixedSize();
}
return ret;
}

protected abstract String getCanonicalDimension();

public SolidityType getElementType() {
return elementType;
Expand All @@ -165,52 +181,40 @@ public static class StaticArrayType extends ArrayType {

public StaticArrayType(String name) {
super(name);
int idx1 = name.indexOf("[");
int idx2 = name.indexOf("]", idx1);
int idx1 = name.lastIndexOf("[");
int idx2 = name.lastIndexOf("]");
String dim = name.substring(idx1 + 1, idx2);
size = Integer.parseInt(dim);
}

@Override
public String getCanonicalName() {
if (elementType instanceof ArrayType) {
String elementTypeName = elementType.getCanonicalName();
int idx1 = elementTypeName.indexOf("[");
return elementTypeName.substring(0, idx1) + "[" + size + "]" + elementTypeName.substring(idx1);
} else {
return elementType.getCanonicalName() + "[" + size + "]";
}
}

@Override
protected String getCanonicalDimension() {
return "[" + size + "]";
return getElementType().getCanonicalName() + "[" + size + "]";
}

@Override
public byte[] encodeList(List l) {
if (l.size() != size) throw new RuntimeException("List size (" + l.size() + ") != " + size + " for type " + getName());
byte[][] elems = new byte[size][];
for (int i = 0; i < l.size(); i++) {
elems[i] = elementType.encode(l.get(i));
}
return ByteUtil.merge(elems);
return encodeTuple(l);
}

@Override
public Object[] decode(byte[] encoded, int offset) {
Object[] result = new Object[size];
for (int i = 0; i < size; i++) {
result[i] = elementType.decode(encoded, offset + i * elementType.getFixedSize());
}

return result;
return decodeTuple(encoded, offset, size);
}

@Override
public int getFixedSize() {
// return negative if elementType is dynamic
return elementType.getFixedSize() * size;
if (isDynamicType()) {
return Int32Size;
} else {
return elementType.getFixedSize() * size;
}
}

@Override
public boolean isDynamicType() {
return getElementType().isDynamicType() && size > 0;
}
}

Expand All @@ -221,60 +225,18 @@ public DynamicArrayType(String name) {

@Override
public String getCanonicalName() {
if (elementType instanceof ArrayType) {
String elementTypeName = elementType.getCanonicalName();
int idx1 = elementTypeName.indexOf("[");
return elementTypeName.substring(0, idx1) + "[]" + elementTypeName.substring(idx1);
} else {
return elementType.getCanonicalName() + "[]";
}
}

@Override
protected String getCanonicalDimension() {
return "[]";
return elementType.getCanonicalName() + "[]";
}

@Override
public byte[] encodeList(List l) {
byte[][] elems;
if (elementType.isDynamicType()) {
elems = new byte[l.size() * 2 + 1][];
elems[0] = IntType.encodeInt(l.size());
int offset = l.size() * 32;
for (int i = 0; i < l.size(); i++) {
elems[i + 1] = IntType.encodeInt(offset);
byte[] encoded = elementType.encode(l.get(i));
elems[l.size() + i + 1] = encoded;
offset += 32 * ((encoded.length - 1) / 32 + 1);
}
} else {
elems = new byte[l.size() + 1][];
elems[0] = IntType.encodeInt(l.size());

for (int i = 0; i < l.size(); i++) {
elems[i + 1] = elementType.encode(l.get(i));
}
}
return ByteUtil.merge(elems);
return ByteUtil.merge(IntType.encodeInt(l.size()), encodeTuple(l));
}

@Override
public Object decode(byte[] encoded, int origOffset) {
int len = IntType.decodeInt(encoded, origOffset).intValue();
origOffset += 32;
int offset = origOffset;
Object[] ret = new Object[len];

for (int i = 0; i < len; i++) {
if (elementType.isDynamicType()) {
ret[i] = elementType.decode(encoded, origOffset + IntType.decodeInt(encoded, offset).intValue());
} else {
ret[i] = elementType.decode(encoded, offset);
}
offset += elementType.getFixedSize();
}
return ret;
return decodeTuple(encoded, origOffset + Int32Size, len);
}

@Override
Expand Down Expand Up @@ -302,7 +264,7 @@ public byte[] encode(Object value) {
} else {
throw new RuntimeException("byte[] or String value is expected for type 'bytes'");
}
byte[] ret = new byte[((bb.length - 1) / 32 + 1) * 32]; // padding 32 bytes
byte[] ret = new byte[((bb.length - 1) / Int32Size + 1) * Int32Size]; // padding 32 bytes
System.arraycopy(bb, 0, ret, 0, bb.length);

return ByteUtil.merge(IntType.encodeInt(bb.length), ret);
Expand All @@ -312,7 +274,7 @@ public byte[] encode(Object value) {
public Object decode(byte[] encoded, int offset) {
int len = IntType.decodeInt(encoded, offset).intValue();
if (len == 0) return new byte[0];
offset += 32;
offset += Int32Size;
return Arrays.copyOfRange(encoded, offset, offset + len);
}

Expand Down Expand Up @@ -350,14 +312,14 @@ public byte[] encode(Object value) {
BigInteger bigInt = new BigInteger(value.toString());
return IntType.encodeInt(bigInt);
} else if (value instanceof String) {
byte[] ret = new byte[32];
byte[] ret = new byte[Int32Size];
byte[] bytes = ((String) value).getBytes(StandardCharsets.UTF_8);
System.arraycopy(bytes, 0, ret, 0, bytes.length);
return ret;
} else if (value instanceof byte[]) {
byte[] bytes = (byte[]) value;
byte[] ret = new byte[32];
System.arraycopy(bytes, 0, ret, 32 - bytes.length, bytes.length);
byte[] ret = new byte[Int32Size];
System.arraycopy(bytes, 0, ret, Int32Size - bytes.length, bytes.length);
return ret;
}

Expand All @@ -370,7 +332,7 @@ public Object decode(byte[] encoded, int offset) {
}

public static byte[] decodeBytes32(byte[] encoded, int offset) {
return Arrays.copyOfRange(encoded, offset, offset + 32);
return Arrays.copyOfRange(encoded, offset, offset + Int32Size);
}
}

Expand Down Expand Up @@ -443,13 +405,13 @@ public String getCanonicalName() {
return super.getCanonicalName();
}
public static BigInteger decodeInt(byte[] encoded, int offset) {
return new BigInteger(Arrays.copyOfRange(encoded, offset, offset + 32));
return new BigInteger(Arrays.copyOfRange(encoded, offset, offset + Int32Size));
}
public static byte[] encodeInt(int i) {
return encodeInt(new BigInteger("" + i));
}
public static byte[] encodeInt(BigInteger bigInt) {
return ByteUtil.bigIntegerToBytesSigned(bigInt, 32);
return ByteUtil.bigIntegerToBytesSigned(bigInt, Int32Size);
}
@Override
public Object decode(byte[] encoded, int offset) {
Expand All @@ -473,7 +435,7 @@ public String getCanonicalName() {
return super.getCanonicalName();
}
public static BigInteger decodeInt(byte[] encoded, int offset) {
return new BigInteger(1, Arrays.copyOfRange(encoded, offset, offset + 32));
return new BigInteger(1, Arrays.copyOfRange(encoded, offset, offset + Int32Size));
}
public static byte[] encodeInt(int i) {
return encodeInt(new BigInteger("" + i));
Expand All @@ -482,7 +444,7 @@ public static byte[] encodeInt(BigInteger bigInt) {
if (bigInt.signum() == -1) {
throw new RuntimeException("Wrong value for uint type: " + bigInt);
}
return ByteUtil.bigIntegerToBytes(bigInt, 32);
return ByteUtil.bigIntegerToBytes(bigInt, Int32Size);
}
@Override
public byte[] encode(Object value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,14 @@ private static <T> List<T> getElementsOf(Class<T> clazz, Option... options) {
public Result compileSrc(byte[] source, boolean optimize, boolean combinedJson, Option... options) throws IOException {
List<String> commandParts = prepareCommandOptions(optimize, combinedJson, options);

//new in solidity 0.5.0: using stdin requires an explicit "-". The following output
//of 'solc' if no file is provided, e.g.,: solc --combined-json abi,bin,interface,metadata
//
// No input files given. If you wish to use the standard input please specify "-" explicitly.
//
// For older solc version "-" is not an issue as it is accepet as well
commandParts.add("-");

ProcessBuilder processBuilder = new ProcessBuilder(commandParts)
.directory(solc.getExecutable().getParentFile());
processBuilder.environment().put("LD_LIBRARY_PATH",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ public Pair<Boolean, byte[]> execute(byte[] data) {

// check if modulus is zero
if (isZero(mod))
return Pair.of(true, EMPTY_BYTE_ARRAY);
return Pair.of(true, new byte[modLen]); // should keep length of the result

byte[] res = stripLeadingZeroes(base.modPow(exp, mod).toByteArray());

Expand Down
Loading

0 comments on commit 304b166

Please sign in to comment.