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

Commit

Permalink
Merge branch 'stage' of https://github.com/ethereum/ethereumj into stage
Browse files Browse the repository at this point in the history
  • Loading branch information
mkalinin committed Mar 4, 2016
2 parents 597bdb0 + b75cf4c commit 5eddb6d
Show file tree
Hide file tree
Showing 37 changed files with 610 additions and 3 deletions.
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
sudo: false
sudo: required
dist: trusty

language: java
jdk: oraclejdk7
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public void run() {
/**
* Is called when the whole blockchain sync is complete
*/
public void onSyncDone() {
public void onSyncDone() throws Exception {
logger.info("Monitoring new blocks in real-time...");
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package org.ethereum.samples;

import org.ethereum.core.Block;
import org.ethereum.core.CallTransaction;
import org.ethereum.core.Transaction;
import org.ethereum.core.TransactionReceipt;
import org.ethereum.db.ByteArrayWrapper;
import org.ethereum.facade.EthereumFactory;
import org.ethereum.listener.EthereumListenerAdapter;
import org.ethereum.solidity.compiler.CompilationResult;
import org.ethereum.solidity.compiler.SolidityCompiler;
import org.ethereum.util.ByteUtil;
import org.ethereum.vm.program.ProgramResult;
import org.spongycastle.util.encoders.Hex;
import org.springframework.context.annotation.Bean;

import java.math.BigInteger;
import java.util.*;

/**
* Created by Anton Nashatyrev on 03.03.2016.
*/
public class CreateContractSample extends TestNetSample {
String contract =
"contract Sample {" +
" int i;" +
" function inc(int n) {" +
" i = i + n;" +
" }" +
" function get() returns (int) {" +
" return i;" +
" }" +
"}";

private Map<ByteArrayWrapper, TransactionReceipt> txWaiters =
Collections.synchronizedMap(new HashMap<ByteArrayWrapper, TransactionReceipt>());

@Override
public void onSyncDone() throws Exception {
ethereum.addListener(new EthereumListenerAdapter() {
// when block arrives look for our included transactions
@Override
public void onBlock(Block block, List<TransactionReceipt> receipts) {
CreateContractSample.this.onBlock(block, receipts);
}
});

logger.info("Compiling contract...");
SolidityCompiler.Result result = SolidityCompiler.compile(contract.getBytes(), true,
SolidityCompiler.Options.ABI, SolidityCompiler.Options.BIN);
if (result.isFailed()) {
throw new RuntimeException("Contract compilation failed:\n" + result.errors);
}
CompilationResult res = CompilationResult.parse(result.output);
if (res.contracts.isEmpty()) {
throw new RuntimeException("Compilation failed, no contracts returned:\n" + result.errors);
}
CompilationResult.ContractMetadata metadata = res.contracts.values().iterator().next();
if (metadata.bin == null || metadata.bin.isEmpty()) {
throw new RuntimeException("Compilation failed, no binary returned:\n" + result.errors);
}

logger.info("Sending contract to net and waiting for inclusion");
TransactionReceipt receipt = sendTxAndWait(new byte[0], Hex.decode(metadata.bin));

byte[] contractAddress = receipt.getTransaction().getContractAddress();
logger.info("Contract created: " + Hex.toHexString(contractAddress));

logger.info("Calling the contract function 'inc'");
CallTransaction.Contract contract = new CallTransaction.Contract(metadata.abi);
CallTransaction.Function inc = contract.getByName("inc");
byte[] functionCallBytes = inc.encode(777);
TransactionReceipt receipt1 = sendTxAndWait(contractAddress, functionCallBytes);
logger.info("Contract modified!");

ProgramResult r = ethereum.callConstantFunction(Hex.toHexString(contractAddress),
contract.getByName("get"));
Object[] ret = contract.getByName("get").decodeResult(r.getHReturn());
logger.info("Current contract data member value: " + ret[0]);
}

protected TransactionReceipt sendTxAndWait(byte[] receiveAddress, byte[] data) throws InterruptedException {
BigInteger nonce = ethereum.getRepository().getNonce(senderAddress);
Transaction tx = new Transaction(
ByteUtil.bigIntegerToBytes(nonce),
ByteUtil.longToBytesNoLeadZeroes(ethereum.getGasPrice()),
ByteUtil.longToBytesNoLeadZeroes(3_000_000),
receiveAddress,
ByteUtil.longToBytesNoLeadZeroes(1),
data);
tx.sign(senderPrivateKey);
logger.info("<=== Sending transaction: " + tx);
ethereum.submitTransaction(tx);

return waitForTx(tx.getHash());
}

private void onBlock(Block block, List<TransactionReceipt> receipts) {
for (TransactionReceipt receipt : receipts) {
ByteArrayWrapper txHashW = new ByteArrayWrapper(receipt.getTransaction().getHash());
if (txWaiters.containsKey(txHashW)) {
txWaiters.put(txHashW, receipt);
synchronized (this) {
notifyAll();
}
}
}
}

protected TransactionReceipt waitForTx(byte[] txHash) throws InterruptedException {
ByteArrayWrapper txHashW = new ByteArrayWrapper(txHash);
txWaiters.put(txHashW, null);
long startBlock = ethereum.getBlockchain().getBestBlock().getNumber();
while(true) {
TransactionReceipt receipt = txWaiters.get(txHashW);
if (receipt != null) {
return receipt;
} else {
long curBlock = ethereum.getBlockchain().getBestBlock().getNumber();
if (curBlock > startBlock + 16) {
throw new RuntimeException("The transaction was not included during last 16 blocks: " + txHashW.toString().substring(0,8));
} else {
logger.info("Waiting for block with transaction 0x" + txHashW.toString().substring(0,8) +
" included (" + (curBlock - startBlock) + " blocks received so far) ...");
}
}
synchronized (this) {
wait(20000);
}
}
}

public static void main(String[] args) throws Exception {
sLogger.info("Starting EthereumJ!");

class Config extends TestNetConfig{
@Override
@Bean
public TestNetSample sampleBean() {
return new CreateContractSample();
}
}

// Based on Config class the BasicSample would be created by Spring
// and its springInit() method would be called as an entry point
EthereumFactory.createEthereum(Config.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public SystemProperties systemProperties() {
}

@Override
public void onSyncDone() {
public void onSyncDone() throws Exception {
super.onSyncDone();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.ethereum.solidity.compiler;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.annotate.JsonProperty;

import java.io.IOException;
import java.util.Map;

@JsonIgnoreProperties(ignoreUnknown = true)
public class CompilationResult {

public Map<String, ContractMetadata> contracts;
public String version;

public static CompilationResult parse(String rawJson) throws IOException {
return new ObjectMapper().readValue(rawJson, CompilationResult.class);
}

@JsonIgnoreProperties(ignoreUnknown = true)
public static class ContractMetadata {
public String abi;
public String bin;
public String solInterface;

public String getInterface() {
return solInterface;
}

public void setInterface(String solInterface) {
this.solInterface = solInterface;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.ethereum.solidity.compiler;

public class ContractException extends RuntimeException {

public ContractException(String message) {
super(message);
}

public static ContractException permissionError(String msg, Object... args) {
return error("contract permission error", msg, args);
}

public static ContractException compilationError(String msg, Object... args) {
return error("contract compilation error", msg, args);
}

public static ContractException validationError(String msg, Object... args) {
return error("contract validation error", msg, args);
}

public static ContractException assembleError(String msg, Object... args) {
return error("contract assemble error", msg, args);
}

private static ContractException error(String title, String message, Object... args) {
return new ContractException(title + ": " + String.format(message, args));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.ethereum.solidity.compiler;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.Scanner;

/**
* Created by Anton Nashatyrev on 03.03.2016.
*/
public class Solc {

public static final Solc INSTANCE = new Solc();

private File solc = null;

private Solc() {
try {
init();
} catch (IOException e) {
throw new RuntimeException("Can't init solc compiler: ", e);
}
}

private void init() throws IOException {
File tmpDir = new File(System.getProperty("java.io.tmpdir"), "solc");
tmpDir.mkdirs();

InputStream is = getClass().getResourceAsStream("/native/" + getOS() + "/solc/file.list");
Scanner scanner = new Scanner(is);
while (scanner.hasNext()) {
String s = scanner.next();
File targetFile = new File(tmpDir, s);
if (!targetFile.canRead()) {
InputStream fis = getClass().getResourceAsStream("/native/" + getOS() + "/solc/" + s);
Files.copy(fis, targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
if (solc == null) {
// first file in the list denotes executable
solc = targetFile;
solc.setExecutable(true);
}
targetFile.deleteOnExit();
}

}

private static String getOS() {
String osName = System.getProperty("os.name").toLowerCase();
if (osName.contains("win")) {
return "win";
} else if (osName.contains("linux")) {
return "linux";
} else if (osName.contains("mac")) {
return "mac";
} else {
throw new RuntimeException("Can't find solc compiler: unrecognized OS: " + osName);
}
}

public File getExecutable() {
return solc;
}
}
Loading

0 comments on commit 5eddb6d

Please sign in to comment.