Merged latest develop changes.

Some interop fixes.
This commit is contained in:
Adrian Tiberius 2015-07-02 22:04:25 +02:00
parent a8dbead829
commit c6288e295d
61 changed files with 925 additions and 3318 deletions

View File

@ -8,6 +8,7 @@ import org.ethereum.android.service.EthereumConnector;
public class EthereumApplication extends MultiDexApplication {
public EthereumConnector ethereum = null;
public String log="";
@Override public void onCreate() {

View File

@ -154,8 +154,13 @@ public class RemoteMainActivity extends ActionBarActivity implements ActivityInt
Date date = new Date(timestamp);
EthereumApplication app = (EthereumApplication)getApplication();
app.log += formatter.format(date) + " -> " + message + "\n\n";
if (app.log.length() > 10000) {
app.log = app.log.substring(5000);
}
for(FragmentInterface fragment: fragments) {
fragment.onMessage(formatter.format(date) + " -> " + message + "\n");
fragment.onMessage(app.log);
}
}

View File

@ -55,6 +55,8 @@ dependencies {
exclude group: "org.hibernate", module: "hibernate-entitymanager"
exclude group: "redis.clients", module: "jedis"
exclude group: "org.antlr", module: "antlr4-runtime"
exclude group: "org.fusesource.leveldbjni", module: "leveldbjni"
exclude group: "org.fusesource.leveldbjni", module: "leveldbjni-all"
}
//compile "com.google.dagger:dagger:2.1-SNAPSHOT"

View File

@ -51,7 +51,7 @@
<appender-ref ref="logcat" />
</logger>
<logger name="db" level="ERROR">
<logger name="db" level="DEBUG">
<appender-ref ref="logcat" />
</logger>
@ -87,7 +87,7 @@
<appender-ref ref="logcat" />
</logger>
<logger name="general" level="ERROR">
<logger name="general" level="DEBUG">
<appender-ref ref="logcat" />
</logger>
@ -99,19 +99,19 @@
<appender-ref ref="logcat" />
</logger>
<logger name="main" level="ERROR">
<logger name="main" level="DEBUG">
<appender-ref ref="logcat" />
</logger>
<logger name="state" level="ERROR">
<logger name="state" level="DEBUG">
<appender-ref ref="logcat" />
</logger>
<logger name="repository" level="ERROR">
<logger name="repository" level="DEBUG">
<appender-ref ref="logcat" />
</logger>
<logger name="blockchain" level="ERROR">
<logger name="blockchain" level="DEBUG">
<appender-ref ref="logcat" />
</logger>
@ -127,7 +127,7 @@
<appender-ref ref="logcat" />
</logger>
<logger name="hsqldb.db" level="ERROR">
<logger name="hsqldb.db" level="DEBUG">
<appender-ref ref="logcat" />
</logger>
@ -135,7 +135,7 @@
<appender-ref ref="logcat" />
</logger>
<root level="INFO">
<root level="DEBUG">
<appender-ref ref="logcat" />
</root>

View File

@ -19,7 +19,9 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static org.iq80.leveldb.impl.Iq80DBFactory.factory;
import static org.fusesource.leveldbjni.JniDBFactory.factory;
//import static org.iq80.leveldb.impl.Iq80DBFactory.factory;
/**
* @author Roman Mandeleil
@ -55,6 +57,7 @@ public class LevelDbDataSource implements KeyValueDataSource {
logger.debug("Opening database");
File dbLocation = new File(SystemProperties.CONFIG.databaseDir());
File fileLocation = new File(dbLocation, name);
if (!dbLocation.exists()) dbLocation.mkdirs();
if (SystemProperties.CONFIG.databaseReset()) {
destroyDB(fileLocation);

View File

@ -137,8 +137,8 @@ public class EthereumModule {
}
@Provides
ShhHandler provideShhHandler(EthereumListener listener) {
return new ShhHandler(listener);
ShhHandler provideShhHandler(WorldManager worldManager) {
return new ShhHandler(worldManager);
}
@Provides

View File

@ -5,7 +5,7 @@ import com.thetransactioncompany.jsonrpc2.server.*;
import org.ethereum.android.jsonrpc.full.JsonRpcServerMethod;
import org.ethereum.core.AccountState;
import org.ethereum.facade.Ethereum;
import org.ethereum.serpent.SerpentCompiler;
//import org.ethereum.serpent.SerpentCompiler;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.util.List;
@ -35,12 +35,12 @@ public class eth_compileSerpent extends JsonRpcServerMethod {
Pattern pattern = Pattern.compile("(.*?)init:(.*?)code:(.*?)", Pattern.DOTALL);
Matcher matcher = pattern.matcher(code);
if (matcher.find()) {
asmResult = SerpentCompiler.compileFullNotion(code);
machineCode = SerpentCompiler.compileFullNotionAssemblyToMachine(asmResult);
//asmResult = SerpentCompiler.compileFullNotion(code);
//machineCode = SerpentCompiler.compileFullNotionAssemblyToMachine(asmResult);
} else {
asmResult = SerpentCompiler.compile(code);
machineCode = SerpentCompiler.compileAssemblyToMachine(asmResult);
machineCode = SerpentCompiler.encodeMachineCodeForVMRun(machineCode, null);
//asmResult = SerpentCompiler.compile(code);
//machineCode = SerpentCompiler.compileAssemblyToMachine(asmResult);
//machineCode = SerpentCompiler.encodeMachineCodeForVMRun(machineCode, null);
}
} catch (Throwable th) {
return new JSONRPC2Response(JSONRPC2Error.INTERNAL_ERROR, req.getID());

View File

@ -444,7 +444,7 @@ public class EthereumRemoteService extends EthereumService {
String identifier = ((Bundle)message.obj).getString("identifier");
clientListeners.put(identifier, message.replyTo);
Bundle data = message.getData();
data.setClassLoader(EnumSet.class.getClassLoader());
data.setClassLoader(EventFlag.class.getClassLoader());
EnumSet<EventFlag> flags = (EnumSet<EventFlag>)data.getSerializable("flags");
EnumSet<EventFlag> list = (flags == null || flags.contains(EventFlag.EVENT_ALL)) ? EnumSet.allOf(EventFlag.class) : flags;
for (EventFlag flag: list) {

View File

@ -54,7 +54,13 @@ public class PendingTransactionsEventData extends EventData {
private PendingTransactionsEventData(Parcel in) {
super(in);
transactions = new HashSet<Transaction>(Arrays.asList((Transaction[])in.readParcelableArray(org.ethereum.android.interop.Transaction.class.getClassLoader())));
Parcelable[] transactions = in.readParcelableArray(org.ethereum.android.interop.Transaction.class.getClassLoader());
Transaction[] txs = new Transaction[transactions.length];
int index = 0;
for (Parcelable transaction: transactions) {
txs[index] = (Transaction)transaction;
}
this.transactions = new HashSet<Transaction>(Arrays.asList(txs));
}
}

View File

@ -17,7 +17,6 @@ plugins {
id 'application'
id 'jacoco'
id 'com.github.johnrengelman.shadow' version '1.2.1'
id 'me.champeau.gradle.antlr4' version '0.1'
id 'com.github.kt3k.coveralls' version '2.0.1x'
id 'com.jfrog.bintray' version '1.0'
}
@ -30,7 +29,7 @@ repositories {
sourceCompatibility = 1.7
mainClassName = 'org.ethereum.Start'
applicationDefaultJvmArgs = ["-server", "-Xss32m"]
applicationDefaultJvmArgs = ["-server", "-Xss32m", "-Xms3500m"]
ext.generatedSrcDir = file('src/gen/java')
@ -45,24 +44,7 @@ sourceSets {
}
}
antlr4 {
extraArgs = ['-package', 'org.ethereum.serpent']
output = file("${generatedSrcDir}/org/ethereum/serpent")
}
if (isJavaProject(project)) {
compileJava.dependsOn antlr4
} else if (isAndroidProject(project)) {
preBuild.dependsOn antlr4
} else {
throw new GradleException('unknown plugin type')
}
public static boolean isJavaProject(Project project) {
project.plugins.findPlugin('java')
}
public static boolean isAndroidProject(Project project) {
project.plugins.findPlugin('com.android.application') || project.plugins.findPlugin('com.android.library')
}
tasks.withType(JavaCompile){
options.warnings = false
@ -108,10 +90,6 @@ test {
systemProperty "file.encoding", "UTF-8"
}
configurations {
compile.extendsFrom antlr4
}
ext {
slf4jVersion = '1.7.12'
leveldbVersion = '0.7'
@ -133,9 +111,10 @@ dependencies {
compile "org.iq80.leveldb:leveldb:${leveldbVersion}"
compile "org.fusesource.leveldbjni:leveldbjni:1.8"
compile "org.fusesource.leveldbjni:leveldbjni-all:1.8"
compile "com.cedarsoftware:java-util:1.8.0" // for deep equals
compile "org.antlr:antlr4-runtime:4.5" // for serpent compilation
compile "com.yuvalshavit:antlr-denter:1.1"
compile "org.javassist:javassist:3.15.0-GA"
compile "org.slf4j:slf4j-api:${slf4jVersion}"
compile "log4j:log4j:${log4jVersion}"
@ -149,7 +128,9 @@ dependencies {
compile "commons-dbcp:commons-dbcp:1.4"
compile "redis.clients:jedis:2.6.0"
compile "com.h2database:h2:1.4.187"
compile "org.mapdb:mapdb:1.0.7"
// compile "org.mapdb:mapdb:1.0.7"
compile "org.mapdb:mapdb:2.0-alpha3"
compile "org.slf4j:slf4j-log4j12:${slf4jVersion}"
compile "log4j:apache-log4j-extras:${log4jVersion}"

View File

@ -1,3 +0,0 @@
*
!.gitignore
!README.md

View File

@ -1,5 +0,0 @@
This is the output directory for transient sources generated from grammars in
the `src/main/antlr4` directory using the `gradle antlr4` task. Sources are
output here instead of the typical `build/generated-src` output directory in
order to avoid confusing IntelliJ IDEA. See the antlr plugin configuration in
`build.gradle` for details.

View File

@ -1,241 +0,0 @@
// @author Roman Mandeleil
// @since 22.03.2014
grammar Serpent;
tokens {
INDENT, DEDENT }
@lexer::header {
import com.yuvalshavit.antlr4.DenterHelper;
}
@lexer::members {
private final DenterHelper denter = new DenterHelper(NL, SerpentParser.INDENT, SerpentParser.DEDENT) {
@Override
public Token pullToken() {
return SerpentLexer.super.nextToken(); // must be to super.nextToken, or we'll recurse forever!
}
};
@Override
public Token nextToken() {
return denter.nextToken();
}
}
parse: block EOF
;
parse_init_code_block : 'init' ':' INDENT block DEDENT 'code' ':' INDENT block DEDENT;
block: ( asm | array_assign | assign | contract_storage_assign | special_func | if_elif_else_stmt |
while_stmt | ret_func_1 | ret_func_2 | suicide_func | stop_func | single_send_func | msg_func |
single_create_func)* ;
asm: '[asm' asm_symbol 'asm]' NL;
asm_symbol: (ASM_SYMBOLS | INT | HEX_NUMBER)* ;
if_elif_else_stmt: 'if' condition ':' INDENT block DEDENT
('elif' condition ':' INDENT block DEDENT)*
('else:' INDENT block DEDENT)?
;
while_stmt: 'while' condition ':' INDENT block DEDENT;
/* special functions */
special_func :
msg_datasize |
msg_sender |
msg_value |
tx_gasprice |
tx_origin |
tx_gas |
contract_balance |
contract_address |
block_prevhash |
block_coinbase |
block_timestamp |
block_number |
block_difficulty |
block_gaslimit
;
msg_datasize
: 'msg.datasize' ;
msg_sender
: 'msg.sender' ;
msg_value
: 'msg.value' ;
tx_gasprice
: 'tx.gasprice' ;
tx_origin
: 'tx.origin' ;
tx_gas
: 'tx.gas' ;
contract_balance
: 'contract.balance' ;
contract_address
: 'contract.address' ;
block_prevhash
: 'block.prevhash' ;
block_coinbase
: 'block.coinbase' ;
block_timestamp
: 'block.timestamp' ;
block_number
: 'block.number' ;
block_difficulty
: 'block.difficulty' ;
block_gaslimit
: 'block.gaslimit' ;
msg_func: 'msg' '(' int_val ',' int_val ',' int_val ',' arr_def ',' int_val ',' int_val')' ;
send_func: 'send' '(' int_val ',' int_val ',' int_val ')';
single_send_func: send_func NL;
create_func: 'create' '(' int_val ',' int_val ',' int_val ')';
single_create_func: create_func NL;
msg_data: 'msg.data' '[' expression ']' ;
array_assign: VAR '[' int_val ']' EQ_OP expression NL;
array_retreive: VAR '[' int_val ']';
assign: VAR EQ_OP (expression | arr_def | msg_func) NL;
arr_def : '[' (int_val ','?)* ']';
contract_storage_assign: 'contract.storage' '[' expression ']' EQ_OP expression NL;
contract_storage_load: 'contract.storage' '[' expression ']';
mul_expr
: int_val
| mul_expr OP_MUL int_val
;
add_expr
: mul_expr
| add_expr OP_ADD mul_expr
;
rel_exp
: add_expr
| rel_exp OP_REL add_expr
;
eq_exp
: rel_exp
| eq_exp OP_EQ rel_exp
;
and_exp
: eq_exp
| and_exp OP_AND eq_exp
;
ex_or_exp
: and_exp
| ex_or_exp OP_EX_OR and_exp
;
in_or_exp
: ex_or_exp
| in_or_exp OP_IN_OR ex_or_exp
;
log_and_exp
: in_or_exp
| log_and_exp OP_LOG_AND in_or_exp
;
log_or_exp
: log_and_exp
| log_or_exp OP_LOG_OR log_and_exp
;
expression : log_or_exp ;
condition: expression ;
int_val : INT |
hex_num |
get_var |
special_func |
'(' expression ')' |
OP_NOT '(' expression ')' |
msg_data |
send_func |
contract_storage_load |
array_retreive
;
hex_num
: HEX_NUMBER
;
ret_func_1: 'return' '(' expression ')' NL;
ret_func_2: 'return' '(' expression ',' expression ')' NL;
suicide_func: 'suicide' '(' expression ')' NL;
stop_func: 'stop' NL;
get_var: VAR;
INT: [0-9]+;
ASM_SYMBOLS: 'STOP' | 'ADD' | 'MUL' | 'SUB' | 'DIV' | 'SDIV' | 'MOD' |'SMOD' | 'EXP' | 'NEG' | 'LT' | 'GT' | 'SLT' | 'SGT'| 'EQ' | 'NOT' | 'AND' | 'OR' | 'XOR' | 'BYTE' | 'SHA3' | 'ADDRESS' | 'BALANCE' | 'ORIGIN' | 'CALLER' | 'CALLVALUE' | 'CALLDATALOAD' | 'CALLDATASIZE' | 'CALLDATACOPY' | 'CODESIZE' | 'CODECOPY' | 'GASPRICE' | 'PREVHASH' | 'COINBASE' | 'TIMESTAMP' | 'NUMBER' | 'DIFFICULTY' | 'GASLIMIT' | 'POP' | 'DUP' | 'SWAP' | 'MLOAD' | 'MSTORE' | 'MSTORE8' | 'SLOAD' | 'SSTORE' | 'JUMP' | 'JUMPI' | 'PC' | 'MSIZE' | 'GAS' | 'PUSH1' | 'PUSH2' | 'PUSH3' | 'PUSH4' | 'PUSH5' | 'PUSH6' | 'PUSH7' | 'PUSH8' | 'PUSH9' | 'PUSH10' | 'PUSH11' | 'PUSH12' | 'PUSH13' | 'PUSH14' | 'PUSH15' | 'PUSH16' | 'PUSH17' | 'PUSH18' | 'PUSH19' | 'PUSH20' | 'PUSH21' | 'PUSH22' | 'PUSH23' | 'PUSH24' | 'PUSH25' | 'PUSH26' | 'PUSH27' | 'PUSH28' | 'PUSH29' | 'PUSH30' | 'PUSH31' | 'PUSH32' | 'CREATE' | 'CALL' | 'RETURN' | 'SUICIDE';
/* 'xor', 'and', 'or', 'not' operands should be defined
first among lexer rules because it
can be mismatched as a var lexa */
OP_EX_OR: 'xor';
OP_LOG_AND: '&&' | 'and';
OP_LOG_OR: '||' | 'or';
OP_NOT: '!' | 'not';
EQ_OP: '=' ;
NL: ('\r'? '\n' ' '*); // note the ' '*;
WS: [ \t]+ -> skip;
LINE_COMMENT: '//' ~[\r\n]* -> skip;
VAR: [a-zA-Z][a-zA-Z0-9]* ;
OP_ADD : '+' | '-';
OP_MUL : '*' | '/' | '^' | '%' | '#/' | '#%' ;
OP_REL : '<' | '>' | '<=' | '>=';
OP_EQ : '==' | '!=';
OP_AND: '&';
OP_IN_OR: '|';
HEX_DIGIT : [0-9a-fA-F];
HEX_NUMBER : ('0x' | '0X' )HEX_DIGIT+;

View File

@ -1,97 +0,0 @@
OP_IN_OR=53
T__29=7
EQ_OP=43
T__28=8
T__27=9
OP_AND=52
T__26=10
T__25=11
T__24=12
T__23=13
T__22=14
T__21=15
T__20=16
OP_MUL=49
DEDENT=57
T__9=27
T__8=28
T__7=29
INDENT=56
T__6=30
T__5=31
T__4=32
T__19=17
OP_EQ=51
T__16=20
T__15=21
T__18=18
T__17=19
T__12=24
T__11=25
T__14=22
T__13=23
T__10=26
OP_EX_OR=39
OP_NOT=42
VAR=47
NL=44
LINE_COMMENT=46
OP_LOG_OR=41
OP_ADD=48
HEX_DIGIT=54
INT=37
T__30=6
T__31=5
T__32=4
T__33=3
WS=45
T__34=2
T__35=1
T__1=35
T__0=36
T__3=33
T__2=34
ASM_SYMBOLS=38
HEX_NUMBER=55
OP_REL=50
OP_LOG_AND=40
'|'=53
'code'=36
'block.number'=35
'block.gaslimit'=34
'asm]'=33
'contract.balance'=32
'msg.sender'=31
'='=43
'return'=30
'elif'=29
'create'=28
'msg.data'=27
'tx.origin'=26
'else:'=25
'tx.gasprice'=24
')'=23
'xor'=39
'msg.datasize'=22
'block.difficulty'=21
'suicide'=20
'block.prevhash'=18
'contract.storage'=19
'init'=17
'msg.value'=16
'[asm'=15
'contract.address'=14
'block.timestamp'=13
'send'=12
'if'=11
'('=10
':'=9
'['=8
'while'=7
'tx.gas'=6
'msg'=5
','=4
'block.coinbase'=3
'&'=52
'stop'=2
']'=1

View File

@ -1,95 +0,0 @@
OP_IN_OR=53
T__29=7
EQ_OP=43
T__28=8
T__27=9
OP_AND=52
T__26=10
T__25=11
T__24=12
T__23=13
T__22=14
T__21=15
T__20=16
OP_MUL=49
T__9=27
T__8=28
T__7=29
T__6=30
T__5=31
T__4=32
T__19=17
OP_EQ=51
T__16=20
T__15=21
T__18=18
T__17=19
T__12=24
T__11=25
T__14=22
T__13=23
T__10=26
OP_EX_OR=39
OP_NOT=42
VAR=47
NL=44
LINE_COMMENT=46
OP_LOG_OR=41
OP_ADD=48
HEX_DIGIT=54
INT=37
T__30=6
T__31=5
T__32=4
T__33=3
WS=45
T__34=2
T__35=1
T__1=35
T__0=36
T__3=33
T__2=34
ASM_SYMBOLS=38
HEX_NUMBER=55
OP_REL=50
OP_LOG_AND=40
'|'=53
'code'=36
'block.number'=35
'block.gaslimit'=34
'asm]'=33
'contract.balance'=32
'msg.sender'=31
'='=43
'return'=30
'elif'=29
'create'=28
'msg.data'=27
'tx.origin'=26
'else:'=25
'tx.gasprice'=24
')'=23
'xor'=39
'msg.datasize'=22
'block.difficulty'=21
'suicide'=20
'block.prevhash'=18
'contract.storage'=19
'init'=17
'msg.value'=16
'[asm'=15
'contract.address'=14
'block.timestamp'=13
'send'=12
'if'=11
'('=10
':'=9
'['=8
'while'=7
'tx.gas'=6
'msg'=5
','=4
'block.coinbase'=3
'&'=52
'stop'=2
']'=1

View File

@ -297,6 +297,7 @@ public class BlockchainImpl implements Blockchain {
if (needFlush(block)) {
repository.flush();
blockStore.flush();
System.gc();
}
// Remove all wallet transactions as they already approved by the net
@ -322,7 +323,7 @@ public class BlockchainImpl implements Blockchain {
private boolean needFlush(Block block) {
boolean isBatchReached = block.getNumber() % CONFIG.flushBatchSize() == 0;
boolean isConsensus = CONFIG.flushIgnoreConsensus() || adminInfo.isConsensus();
return isConsensus && isBatchReached;
}

View File

@ -257,8 +257,12 @@ public class TransactionExecutor {
}
}
if (result.getException() != null)
if (result.getException() != null){
result.getDeleteAccounts().clear();
result.getLogInfoList().clear();
result.futureRefundGas(0);
throw result.getException();
}
} catch (Throwable e) {

View File

@ -1,24 +1,19 @@
package org.ethereum.datasource;
import org.ethereum.config.SystemProperties;
import org.iq80.leveldb.CompressionType;
import org.iq80.leveldb.DB;
import org.iq80.leveldb.DBIterator;
import org.iq80.leveldb.Options;
import org.iq80.leveldb.WriteBatch;
import org.iq80.leveldb.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static org.iq80.leveldb.impl.Iq80DBFactory.factory;
import static org.fusesource.leveldbjni.JniDBFactory.factory;
//import static org.iq80.leveldb.impl.Iq80DBFactory.factory;
/**
* @author Roman Mandeleil
@ -55,6 +50,7 @@ public class LevelDbDataSource implements KeyValueDataSource {
File dbLocation = new File(System.getProperty("user.dir") + "/" +
SystemProperties.CONFIG.databaseDir() + "/");
File fileLocation = new File(dbLocation, name);
if (!dbLocation.exists()) dbLocation.mkdirs();
if (SystemProperties.CONFIG.databaseReset()) {
destroyDB(fileLocation);
@ -104,26 +100,33 @@ public class LevelDbDataSource implements KeyValueDataSource {
@Override
public Set<byte[]> keys() {
try {
try (DBIterator dbIterator = db.iterator()) {
Set<byte[]> keys = new HashSet<>();
while (dbIterator.hasNext()) {
keys.add(dbIterator.next().getKey());
}
DBIterator dbIterator = db.iterator();
Set<byte[]> keys = new HashSet<>();
while (dbIterator.hasNext()) {
Map.Entry<byte[], byte[]> entry = dbIterator.next();
keys.add(entry.getKey());
return keys;
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return keys;
}
@Override
public void updateBatch(Map<byte[], byte[]> rows) {
try {
try (WriteBatch batch = db.createWriteBatch()) {
for (Map.Entry<byte[], byte[]> row : rows.entrySet()) {
batch.put(row.getKey(), row.getValue());
}
WriteBatch batch = db.createWriteBatch();
for (Map.Entry<byte[], byte[]> row : rows.entrySet())
batch.put(row.getKey(), row.getValue());
db.write(batch);
db.write(batch);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override

View File

@ -2,25 +2,22 @@ package org.ethereum.datasource.mapdb;
import org.ethereum.config.SystemProperties;
import org.ethereum.datasource.KeyValueDataSource;
import org.ethereum.db.ByteArrayWrapper;
import org.mapdb.DB;
import org.mapdb.DBMaker;
import org.mapdb.HTreeMap;
import org.mapdb.Serializer;
import java.io.File;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static java.lang.System.getProperty;
import static org.ethereum.util.ByteUtil.wrap;
public class MapDBDataSource implements KeyValueDataSource {
private static final int BATCH_SIZE = 1024 * 1000 * 10;
private DB db;
private HTreeMap<ByteArrayWrapper, byte[]> map;
private Map<byte[], byte[]> map;
private String name;
@Override
@ -30,16 +27,16 @@ public class MapDBDataSource implements KeyValueDataSource {
dbLocation.mkdirs();
}
db = DBMaker.newFileDB(new File(dbLocation, name))
.asyncWriteEnable()
.mmapFileEnableIfSupported()
// .compressionEnable()
.cacheDisable()
// .asyncWriteFlushDelay(1000)
db = DBMaker.fileDB(new File(dbLocation, name))
.transactionDisable()
.closeOnJvmShutdown()
.make();
this.map = db.createHashMap(name).makeOrGet();
this.map = db.hashMapCreate(name)
.keySerializer(Serializer.BYTE_ARRAY)
.valueSerializer(Serializer.BYTE_ARRAY)
.makeOrGet();
}
@Override
@ -49,13 +46,13 @@ public class MapDBDataSource implements KeyValueDataSource {
@Override
public byte[] get(byte[] key) {
return map.get(wrap(key));
return map.get(key);
}
@Override
public byte[] put(byte[] key, byte[] value) {
try {
return map.put(wrap(key), value);
return map.put(key, value);
} finally {
db.commit();
}
@ -72,11 +69,7 @@ public class MapDBDataSource implements KeyValueDataSource {
@Override
public Set<byte[]> keys() {
HashSet<byte[]> result = new HashSet<>();
for (ByteArrayWrapper key : map.keySet()) {
result.add(key.getData());
}
return result;
return map.keySet();
}
@Override
@ -86,8 +79,8 @@ public class MapDBDataSource implements KeyValueDataSource {
for (byte[] key : rows.keySet()) {
byte[] value = rows.get(key);
savedSize += value.length;
map.put(wrap(key), value);
map.put(key, value);
if (savedSize > BATCH_SIZE) {
db.commit();
savedSize = 0;

View File

@ -28,6 +28,8 @@ public interface Database {
*/
public void delete(byte[] key);
void init();
/**
* Close the database connection
*/

View File

@ -64,6 +64,11 @@ public class DatabaseImpl implements Database {
return this.keyValueDataSource;
}
@Override
public void init(){
keyValueDataSource.init();
}
@Override
public void close() {

View File

@ -4,6 +4,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@ -11,7 +13,6 @@ import java.util.Set;
import static java.lang.String.format;
import static org.ethereum.util.ByteUtil.wrap;
import static org.spongycastle.util.encoders.Hex.decode;
public class DetailsDataStore {
@ -64,15 +65,10 @@ public class DetailsDataStore {
public void flush() {
long keys = cache.size();
ByteArrayWrapper largeDetailsKey = wrap(decode("b61662398570293e4f0d25525e2b3002b7fe0836"));
ContractDetails largeDetails = cache.get(largeDetailsKey);
long start = System.nanoTime();
long totalSize = flushInternal();
long finish = System.nanoTime();
if (largeDetails != null) cache.put(largeDetailsKey, largeDetails);
float flushSize = (float) totalSize / 1_048_576;
float flushTime = (float) (finish - start) / 1_000_000;
gLogger.info(format("Flush details in: %02.2f ms, %d keys, %02.2fMB", flushTime, keys, flushSize));
@ -110,4 +106,14 @@ public class DetailsDataStore {
return keys;
}
private void temporarySave(String addr, byte[] data){
try {
FileOutputStream fos = new FileOutputStream(addr);
fos.write(data);
fos.close();
System.out.println("drafted: " + addr);
} catch (IOException e) {e.printStackTrace();}
}
}

View File

@ -79,4 +79,9 @@ public class TrackDatabase implements Database {
public void close() {
db.close();
}
@Override
public void init() {
}
}

View File

@ -124,8 +124,8 @@ public class EthereumModule {
}
@Provides
ShhHandler provideShhHandler(EthereumListener listener) {
return new ShhHandler(listener);
ShhHandler provideShhHandler(WorldManager worldManager) {
return new ShhHandler(worldManager);
}
@Provides

View File

@ -62,12 +62,13 @@ public class BlockLoader {
if (block.getNumber() % 10000 == 0)
System.out.println("Skipping block #" + block.getNumber());
}
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(" * Done * ");
System.exit(0);
}

View File

@ -148,8 +148,6 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
case NEW_BLOCK:
msgQueue.receivedMessage(msg);
processNewBlock((NewBlockMessage) msg);
case PACKET_COUNT:
break;
default:
break;
}

View File

@ -74,12 +74,8 @@ public enum EthMessageCodes {
* in the list (following the message ID) is a block in the format described
* in the main Ethereum specification.
*/
NEW_BLOCK(0x07),
NEW_BLOCK(0x07);
/**
* [+0x08
*/
PACKET_COUNT(0X08);
static byte OFFSET = 0;
private int cmd;
@ -101,7 +97,7 @@ public enum EthMessageCodes {
}
public static boolean inRange(byte code) {
return code >= STATUS.asByte() && code <= PACKET_COUNT.asByte();
return code >= STATUS.asByte() && code <= NEW_BLOCK.asByte();
}
public static void setOffset(byte offset) {

View File

@ -1,43 +0,0 @@
package org.ethereum.net.eth;
import org.ethereum.net.p2p.PongMessage;
import org.ethereum.util.RLP;
/**
* Wrapper around an Ethereum Ping message on the network
*/
public class PacketCountMessage extends EthMessage {
public PacketCountMessage() {
encode();
}
public PacketCountMessage(byte[] payload) {
this.encoded = payload;
}
public byte[] getEncoded() {
return this.encoded;
}
private void encode() {
this.encoded = RLP.encodeList(new byte[]{EthMessageCodes.STATUS.asByte()});
}
@Override
public Class<PongMessage> getAnswerMessage() {
return PongMessage.class;
}
@Override
public EthMessageCodes getCommand() {
return EthMessageCodes.PACKET_COUNT;
}
@Override
public String toString() {
return "[" + getCommand().name() + "]";
}
}

View File

@ -1,20 +1,12 @@
package org.ethereum.net.message;
import org.ethereum.net.eth.BlockHashesMessage;
import org.ethereum.net.eth.BlocksMessage;
import org.ethereum.net.eth.EthMessageCodes;
import org.ethereum.net.eth.GetBlockHashesMessage;
import org.ethereum.net.eth.GetBlocksMessage;
import org.ethereum.net.eth.NewBlockMessage;
import org.ethereum.net.eth.PacketCountMessage;
import org.ethereum.net.eth.StatusMessage;
import org.ethereum.net.eth.TransactionsMessage;
import org.ethereum.net.eth.*;
import org.ethereum.net.p2p.DisconnectMessage;
import org.ethereum.net.p2p.HelloMessage;
import org.ethereum.net.p2p.P2pMessageCodes;
import org.ethereum.net.p2p.PeersMessage;
import org.ethereum.net.shh.Envelope;
import org.ethereum.net.shh.ShhMessageCodes;
import org.ethereum.util.RLP;
/**
* Factory to create protocol message objects based on the RLP encoded data
@ -62,8 +54,6 @@ public class MessageFactory {
return new BlocksMessage(encoded);
case NEW_BLOCK:
return new NewBlockMessage(encoded);
case PACKET_COUNT:
return new PacketCountMessage(encoded);
}
}
@ -72,9 +62,9 @@ public class MessageFactory {
ShhMessageCodes receivedCommand = ShhMessageCodes.fromByte(code);
switch (receivedCommand) {
case STATUS:
break;
return new org.ethereum.net.shh.StatusMessage(encoded);
case MESSAGE:
break;
return new Envelope(encoded);
case ADD_FILTER:
break;
case REMOVE_FILTER:

View File

@ -211,9 +211,9 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
capability.getVersion() == ShhHandler.VERSION) {
// Activate ShhHandler for this peer
// ShhHandler shhHandler =
// (ShhHandler) ctx.pipeline().get(Capability.SHH);
// shhHandler.activate();
ShhHandler shhHandler = channel.getShhHandler();
ctx.pipeline().addLast(Capability.SHH, shhHandler);
shhHandler.activate();
}
capInCommon.add(capability);
}
@ -256,17 +256,17 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
public void adaptMessageIds(List<Capability> capabilities) {
Collections.sort(capabilities);
byte offset = (byte) (P2pMessageCodes.USER.asByte() + 1);
int offset = P2pMessageCodes.USER.asByte() + 1;
for (Capability capability : capabilities) {
if (capability.getName().equals(Capability.ETH)) {
EthMessageCodes.setOffset(offset);
EthMessageCodes.setOffset((byte)offset);
offset += EthMessageCodes.values().length;
}
if (capability.getName().equals(Capability.SHH)) {
ShhMessageCodes.setOffset(offset);
ShhMessageCodes.setOffset((byte)offset);
offset += ShhMessageCodes.values().length;
}
}

View File

@ -4,15 +4,12 @@ import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import org.antlr.v4.runtime.misc.Triple;
import org.ethereum.crypto.ECKey;
import org.ethereum.net.rlpx.*;
import org.ethereum.net.rlpx.discover.table.KademliaOptions;
import org.ethereum.net.rlpx.discover.table.NodeTable;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.net.InetSocketAddress;
import java.util.*;

View File

@ -7,22 +7,18 @@ import org.ethereum.util.RLPElement;
import org.ethereum.util.RLPList;
import org.spongycastle.util.encoders.Hex;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
import java.util.*;
import static org.ethereum.net.shh.ShhMessageCodes.MESSAGE;
import static org.ethereum.crypto.HashUtil.sha3;
/**
* Created by kest on 6/12/15.
* @author by Konstantin Shabalin
*/
public class Envelope extends ShhMessage {
private long expire;
private long ttl;
private int expire;
private int ttl;
private Topic[] topics;
private byte[] data;
@ -33,8 +29,8 @@ public class Envelope extends ShhMessage {
super(encoded);
}
public Envelope(long ttl, Topic[] topics, Message msg) {
this.expire = System.currentTimeMillis() + ttl;
public Envelope(int ttl, Topic[] topics, Message msg) {
this.expire = (int)(System.currentTimeMillis()/1000 + ttl);
this.ttl = ttl;
this.topics = topics;
this.data = msg.getBytes();
@ -45,12 +41,14 @@ public class Envelope extends ShhMessage {
if (!parsed) {
parse();
}
byte[] data = this.data;
long sent = this.expire - this.ttl;
byte[] data = this.data;
int sent = this.expire - this.ttl;
int flags = data[0] < 0 ? (data[0] & 0xFF) : data[0];
Message m = new Message(data[0], sent, this.ttl, hash());
if ((m.getFlags() & Message.SIGNATURE_FLAG) == Message.SIGNATURE_FLAG) {
if ((flags & Message.SIGNATURE_FLAG) == Message.SIGNATURE_FLAG) {
if (data.length < Message.SIGNATURE_LENGTH) {
throw new Error("Unable to open the envelope. First bit set but len(data) < len(signature)");
}
@ -70,17 +68,21 @@ public class Envelope extends ShhMessage {
return m;
}
m.decrypt(privKey);
if (!m.decrypt(privKey)) {
return null;
}
return m;
}
private void parse() {
if (encoded == null) encode();
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
if (isEmpty()) return;
this.expire = ByteUtil.byteArrayToLong(paramsList.get(0).getRLPData());
this.ttl = ByteUtil.byteArrayToLong(paramsList.get(1).getRLPData());
RLPList paramsList = (RLPList)((RLPList) RLP.decode2(encoded).get(0)).get(0);
this.expire = ByteUtil.byteArrayToInt(paramsList.get(0).getRLPData());
this.ttl = ByteUtil.byteArrayToInt(paramsList.get(1).getRLPData());
List<Topic> topics = new ArrayList<>();
RLPList topicsList = (RLPList) RLP.decode2(paramsList.get(2).getRLPData()).get(0);
@ -98,7 +100,7 @@ public class Envelope extends ShhMessage {
private void encode() {
byte[] expire = RLP.encode(this.expire);
byte[] ttl = RLP.encode(this.expire);
byte[] ttl = RLP.encode(this.ttl);
List<byte[]> topics = new Vector<>();
for (Topic t : this.topics) {
@ -110,38 +112,48 @@ public class Envelope extends ShhMessage {
byte[] data = RLP.encodeElement(this.data);
byte[] nonce = RLP.encodeInt(this.nonce);
this.encoded = RLP.encodeList(expire, ttl, encodedTopics, data, nonce);
this.encoded = RLP.encodeList(RLP.encodeList(expire, ttl, encodedTopics, data, nonce));
}
private byte[] encodeWithoutNonce() {
byte[] expire = RLP.encode(this.expire);
byte[] ttl = RLP.encode(this.expire);
List<byte[]> topics = new Vector<>();
for (Topic t : this.topics) {
topics.add(RLP.encodeElement(t.getBytes()));
}
byte[][] topicsArray = topics.toArray(new byte[topics.size()][]);
byte[] encodedTopics = RLP.encodeList(topicsArray);
byte[] data = RLP.encodeElement(this.data);
return RLP.encodeList(expire, ttl, encodedTopics, data);
}
//TODO: complete the nonce implementation
public void seal(long pow) {
byte[] d = new byte[64];
Arrays.fill(d, (byte) 0);
byte[] rlp = encodeWithoutNonce();
encode();
byte[] rlp = this.encoded;
int l = rlp.length < 32 ? rlp.length : 32;
System.arraycopy(rlp, 0, d, 0, l);
long then = System.currentTimeMillis() + pow;
this.nonce = 0;
for (int bestBit = 0; System.currentTimeMillis() < then; ) {
for (int i = 0; i < 1024; ++i, ++bestBit) {
for (int bestBit = 0; System.currentTimeMillis() < then;) {
for (int i = 0, nonce = 0; i < 1024; ++i, ++nonce) {
byte[] nonceBytes = intToByteArray(nonce);
System.arraycopy(nonceBytes, 0, d, 60, nonceBytes.length);
int fbs = getFirstBitSet(sha3(d));
if (fbs > bestBit) {
this.nonce = nonce;
bestBit = fbs;
}
}
}
this.encoded = null;
}
private int getFirstBitSet(byte[] bytes) {
BitSet b = BitSet.valueOf(bytes);
for (int i = 0; i < b.length(); i++) {
if (b.get(i)) {
return i;
}
}
return 0;
}
private byte[] intToByteArray(int value) {
return new byte[] {
(byte)(value >>> 24),
(byte)(value >>> 16),
(byte)(value >>> 8),
(byte)value};
}
private byte[] hash() {
@ -177,6 +189,22 @@ public class Envelope extends ShhMessage {
return data;
}
public boolean isEmpty() {
if (encoded == null) encode();
return encoded.length < 2;
}
private String topicsToString() {
StringBuilder topics = new StringBuilder();
topics.append("[");
for (Topic t : this.topics) {
topics.append(Hex.toHexString(t.getBytes()));
topics.append(", ");
}
topics.append("]");
return topics.toString();
}
@Override
public ShhMessageCodes getCommand() {
return MESSAGE;
@ -195,6 +223,17 @@ public class Envelope extends ShhMessage {
@Override
public String toString() {
return this.toString();
if (!parsed) parse();
if (isEmpty()) {
return "[" + this.getCommand().name() + " empty envelope]";
} else {
return "[" + this.getCommand().name() +
" expire=" + this.expire +
" ttl=" + this.ttl +
" topics=" + topicsToString() +
" data=" + Hex.toHexString(this.data) +
" nonce=" + Hex.toHexString(new byte[]{(byte) this.nonce}) +
"]";
}
}
}

View File

@ -0,0 +1,79 @@
package org.ethereum.net.shh;
import java.util.Arrays;
import java.util.List;
public class Filter {
private byte[] to;
private byte[] from;
private TopicMatcher filterTopics;
public Filter(byte[] to, byte[] from, TopicMatcher filterTopics) {
this.to = to;
this.from = from;
this.filterTopics = filterTopics;
}
public Filter(Message m, Topic[] topics) {
this.to = m.getTo();
this.from = m.getPubKey();
this.filterTopics = new TopicMatcher(topics);
}
public byte[] getTo() {
return to;
}
public void setTo(byte[] to) {
this.to = to;
}
public byte[] getFrom() {
return from;
}
public void setFrom(byte[] from) {
this.from = from;
}
public TopicMatcher getFilterTopics() {
return filterTopics;
}
public void setFilterTopics(TopicMatcher filterTopics) {
this.filterTopics = filterTopics;
}
public List<Topic> getTopics() {
return filterTopics.getTopics();
}
public boolean match(Filter f) {
if (this.to != null) {
if (!Arrays.equals(this.to, f.getTo())) {
return false;
}
}
if (this.from != null) {
if (!Arrays.equals(this.from, f.getFrom())) {
return false;
}
}
if (this.filterTopics != null) {
Topic[] topics = new Topic[f.getTopics().size()];
f.getTopics().toArray(topics);
return this.filterTopics.matches(topics);
}
return true;
}
public void trigger() {
System.out.print("Trigger is called.");
}
}

View File

@ -5,7 +5,9 @@ import org.ethereum.crypto.ECKey;
import org.spongycastle.util.BigIntegers;
import org.spongycastle.math.ec.ECPoint;
import org.spongycastle.util.encoders.Hex;
import java.nio.charset.Charset;
import java.security.SignatureException;
import java.util.Random;
@ -14,20 +16,23 @@ import static org.ethereum.net.shh.ShhMessageCodes.MESSAGE;
import static org.ethereum.util.ByteUtil.merge;
/**
* Created by kest on 6/12/15.
* @author by Konstantin Shabalin
*/
public class Message extends ShhMessage {
private byte flags;
private byte[] signature;
private byte[] payload;
private byte[] to;
private long sent;
private long ttl;
private int sent;
private int ttl;
private byte[] envelopeHash;
public static final byte SIGNATURE_FLAG = 127;
private boolean decrypted;
public static final int SIGNATURE_FLAG = 128;
public static final int SIGNATURE_LENGTH = 65;
// public Message(byte[] encoded) {
@ -39,21 +44,24 @@ public class Message extends ShhMessage {
Random r = new Random();
byte[] randByte = new byte[1];
r.nextBytes(randByte);
flags = randByte[0];
if (flags < 0) {
flags = (byte)(flags & 0xF);
}
int flags = r.nextInt(256);
// if (flags < 0) {
// flags = (byte)(flags & 0xF);
// }
flags &= ~SIGNATURE_FLAG;
this.sent = System.currentTimeMillis();
this.sent = (int) (System.currentTimeMillis()/1000);
this.payload = payload;
this.flags = (byte) flags;
this.decrypted = false;
}
public Message(byte flags, long sent, long ttl, byte[] envelopeHash) {
public Message(byte flags, int sent, int ttl, byte[] envelopeHash) {
this.flags = flags;
this.sent = sent;
this.ttl = ttl;
this.envelopeHash = envelopeHash;
this.decrypted = false;
}
public Envelope wrap(long pow, Options options) {
@ -67,9 +75,18 @@ public class Message extends ShhMessage {
}
Envelope e = new Envelope(options.getTtl(), options.getTopics(), this);
e.seal(pow);
return e;
}
public byte[] getTo() {
return to;
}
public void setTo(byte[] to) {
this.to = to;
}
public byte getFlags() {
return flags;
}
@ -103,6 +120,7 @@ public class Message extends ShhMessage {
ECKey key = ECKey.fromPublicOnly(toPublicKey);
ECPoint pubKeyPoint = key.getPubKeyPoint();
payload = ECIESCoder.encrypt(pubKeyPoint, payload);
this.decrypted = true;
} catch (Exception e) {
}
@ -111,6 +129,8 @@ public class Message extends ShhMessage {
public boolean decrypt(ECKey privateKey) {
try {
payload = ECIESCoder.decrypt(privateKey.getPrivKey(), payload);
this.decrypted = false;
setTo(privateKey.decompress().getPubKey());
return true;
} catch (Exception e) {
System.out.println("The message payload isn't encrypted or something is wrong");
@ -159,6 +179,14 @@ public class Message extends ShhMessage {
return outKey;
}
public byte[] getPubKey() {
ECKey key = recover();
if (key != null) {
return key.decompress().getPubKey();
}
return null;
}
private byte[] hash() {
return sha3(merge(new byte[]{flags}, payload));
}
@ -180,7 +208,20 @@ public class Message extends ShhMessage {
@Override
public String toString() {
return this.toString();
StringBuilder sb = new StringBuilder();
sb.append("[");
sb.append(" flags=" + Hex.toHexString(new byte[]{flags}));
if (signature != null) {
sb.append(" signature=" + Hex.toHexString(signature));
}
if (payload != null) {
sb.append(" payload=" + new String(this.payload, Charset.forName("UTF-8")));
}
if (getPubKey() != null) {
sb.append(" publicKey=" + Hex.toHexString(getPubKey()));
}
sb.append("]");
return sb.toString();
}
}

View File

@ -3,15 +3,19 @@ package org.ethereum.net.shh;
import org.ethereum.crypto.ECKey;
/**
* Created by kest on 6/13/15.
* @author by Konstantin Shabalin
*/
public class Options {
public static int DEFAULT_TTL = 100;
public static int DEFAULT_POW = 50;
private ECKey privateKey;
private byte[] toPublicKey;
private Topic[] topics;
private long ttl;
private int ttl;
public Options(ECKey privateKey, byte[] toPublicKey, Topic[] topics, long ttl) {
public Options(ECKey privateKey, byte[] toPublicKey, Topic[] topics, int ttl) {
this.privateKey = privateKey;
this.toPublicKey = toPublicKey;
this.topics = topics;
@ -42,11 +46,11 @@ public class Options {
this.topics = topics;
}
public long getTtl() {
public int getTtl() {
return ttl;
}
public void setTtl(long ttl) {
public void setTtl(int ttl) {
this.ttl = ttl;
}
}

View File

@ -1,11 +1,15 @@
package org.ethereum.net.shh;
import org.ethereum.listener.EthereumListener;
import org.ethereum.crypto.ECKey;
import org.ethereum.facade.Blockchain;
import org.ethereum.manager.WorldManager;
import org.ethereum.net.MessageQueue;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.ethereum.net.eth.*;
import org.ethereum.util.ByteUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -18,25 +22,32 @@ import javax.inject.Inject;
*/
public class ShhHandler extends SimpleChannelInboundHandler<ShhMessage> {
public final static byte VERSION = 1;
public final static byte VERSION = 2;
private MessageQueue msgQueue = null;
private ECKey privKey;
private Whisper whisper;
private boolean active = false;
private final static Logger logger = LoggerFactory.getLogger("net");
public EthereumListener listener;
WorldManager worldManager;
@Inject
public ShhHandler(EthereumListener listener) {
this.listener = listener;
public ShhHandler(WorldManager worldManager) {
this.worldManager = worldManager;
}
public ShhHandler(MessageQueue msgQueue) {
this.msgQueue = msgQueue;
}
public void setPrivKey(ECKey privKey) {
this.privKey = privKey;
}
@Override
public void channelRead0(final ChannelHandlerContext ctx, ShhMessage msg) throws InterruptedException {
@ -45,12 +56,14 @@ public class ShhHandler extends SimpleChannelInboundHandler<ShhMessage> {
if (ShhMessageCodes.inRange(msg.getCommand().asByte()))
logger.info("ShhHandler invoke: [{}]", msg.getCommand());
listener.trace(String.format("ShhHandler invoke: [%s]", msg.getCommand()));
worldManager.getListener().trace(String.format("ShhHandler invoke: [%s]", msg.getCommand()));
switch (msg.getCommand()) {
case STATUS:
worldManager.getListener().trace("[Recv: " + msg + "]");
break;
case MESSAGE:
whisper.processEnvelope((Envelope) msg);
break;
case ADD_FILTER:
break;
@ -78,10 +91,25 @@ public class ShhHandler extends SimpleChannelInboundHandler<ShhMessage> {
public void activate() {
logger.info("SHH protocol activated");
listener.trace("SHH protocol activated");
worldManager.getListener().trace("SHH protocol activated");
whisper = new Whisper(msgQueue);
sendStatus();
this.active = true;
}
private void sendStatus() {
byte protocolVersion = ShhHandler.VERSION;
StatusMessage msg = new StatusMessage(protocolVersion);
msgQueue.sendMessage(msg);
}
private void processEnvelop(Envelope envelope) {
if (!envelope.isEmpty()) {
Message m = envelope.open(privKey);
logger.info("ShhHandler invoke: [{}]", m);
}
}
public boolean isActive() {
return active;
}

View File

@ -0,0 +1,58 @@
package org.ethereum.net.shh;
import org.ethereum.util.RLP;
import org.ethereum.util.RLPList;
import static org.ethereum.net.shh.ShhMessageCodes.STATUS;
/**
* @author by Konstantin Shabalin
*/
public class StatusMessage extends ShhMessage {
private byte protocolVersion;
public StatusMessage(byte[] encoded) {
super(encoded);
}
public StatusMessage(byte protocolVersion) {
this.protocolVersion = protocolVersion;
this.parsed = true;
}
private void encode() {
byte[] protocolVersion = RLP.encodeByte(this.protocolVersion);
this.encoded = RLP.encodeList(protocolVersion);
}
private void parse() {
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
this.protocolVersion = paramsList.get(0).getRLPData()[0];
parsed = true;
}
@Override
public byte[] getEncoded() {
if (encoded == null) encode();
return encoded;
}
@Override
public Class<?> getAnswerMessage() {
return null;
}
@Override
public ShhMessageCodes getCommand() {
return STATUS;
}
@Override
public String toString() {
if (!parsed) parse();
return "[" + this.getCommand().name() +
" protocolVersion=" + this.protocolVersion + "]";
}
}

View File

@ -1,9 +1,11 @@
package org.ethereum.net.shh;
import java.util.Arrays;
import static org.ethereum.crypto.HashUtil.sha3;
/**
* Created by kest on 6/12/15.
* @author by Konstantin Shabalin
*/
public class Topic {
@ -11,15 +13,37 @@ public class Topic {
private byte[] topic = new byte[4];
public Topic(byte[] data) {
byte[] topic = sha3(data);
System.arraycopy(topic, 0, this.topic, 0, 4);
this.topic = data;
}
public Topic(String data) {
this(data.getBytes());
this.topic = buildTopic(data.getBytes());
}
public byte[] getBytes() {
return topic;
}
private byte[] buildTopic(byte[] data) {
byte[] hash = sha3(data);
byte[] topic = new byte[4];
System.arraycopy(hash, 0, topic, 0, 4);
return topic;
}
public static Topic[] createTopics(String[] topicsString) {
Topic[] topics = new Topic[topicsString.length];
for (int i = 0; i < topicsString.length; i++) {
topics[i] = new Topic(topicsString[i]);
}
return topics;
}
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (obj == this) return true;
if (!(obj instanceof Topic))return false;
return Arrays.equals(this.topic, ((Topic) obj).getBytes());
}
}

View File

@ -0,0 +1,50 @@
package org.ethereum.net.shh;
import java.util.ArrayList;
import java.util.List;
public class TopicMatcher {
private List<List<Topic>> conditions = new ArrayList<>();
public TopicMatcher(Topic[] inputTopics) {
for (Topic t : inputTopics) {
List<Topic> topics = new ArrayList<>();
topics.add(t);
conditions.add(topics);
}
}
public TopicMatcher(String[] topicStrings) {
for (String s : topicStrings) {
List<Topic> topics = new ArrayList<>();
for (String t : s.split(" ")) {
topics.add(new Topic(t));
}
conditions.add(topics);
}
}
public boolean matches(Topic[] topics) {
if (conditions.size() > topics.length) {
return false;
}
for (int i = 0; i < conditions.size() && i < topics.length; i++) {
if (conditions.get(i).size() > 0) {
if (!conditions.get(i).contains(topics[i])) {
return false;
}
}
}
return true;
}
public List<Topic> getTopics() {
List<Topic> topics = new ArrayList<>();
for (List<Topic> topicsList : conditions) {
topics.addAll(topicsList);
}
return topics;
}
}

View File

@ -0,0 +1,124 @@
package org.ethereum.net.shh;
import org.ethereum.crypto.ECKey;
import org.ethereum.net.MessageQueue;
import org.spongycastle.util.encoders.Hex;
import java.util.*;
public class Whisper {
private MessageQueue msgQueue = null;
private Set<Filter> filters = new HashSet<>();
private Set<Message> messages = new HashSet<>();
private Set<Message> known = new HashSet<>();
private Map<String, ECKey> identities = new HashMap<>();
public Whisper(MessageQueue messageQueue) {
this.msgQueue = messageQueue;
}
public void post(String from, String to, String[] topics, String payload, int ttl, int pow) {
Topic[] topicList = Topic.createTopics(topics);
Message m = new Message(payload.getBytes());
ECKey key = null;
if (from != null && !from.isEmpty()) {
key = getIdentity(from);
if (key == null) {
throw new Error(String.format("Unknown identity to send from %s", from));
}
}
Options options = new Options(
key,
Hex.decode(to),
topicList,
ttl
);
Envelope e = m.wrap(pow, options);
addMessage(m, e.getTopics());
msgQueue.sendMessage(e);
}
public void processEnvelope(Envelope e) {
Message m = open(e);
if (m == null) {
return;
}
addMessage(m, e.getTopics());
}
private Message open(Envelope e) {
Message m;
for (ECKey key : identities.values()) {
m = e.open(key);
if (m != null) {
return m;
}
}
m = e.open(null);
return m;
}
public void watch(Filter f) {
filters.add(f);
}
public void unwatch(Filter f) {
filters.remove(f);
}
private void addMessage(Message m, Topic[] topics) {
known.add(m);
matchMessage(m, topics);
}
public Filter createFilter(byte[] to, byte[] from, Topic[] topics) {
TopicMatcher topicMatcher = new TopicMatcher(topics);
Filter f = new Filter(to, from, topicMatcher);
return f;
}
private void matchMessage(Message m, Topic[] topics) {
Filter msgFilter = createFilter(m.getTo(), m.getPubKey(), topics);
for (Filter f : filters) {
if (f.match(msgFilter)) {
f.trigger();
}
}
}
public ECKey newIdentity() {
ECKey key = new ECKey().decompress();
identities.put(Hex.toHexString(key.getPubKey()), key);
return key;
}
public ECKey getIdentity(String keyHexString) {
if (identities.containsKey(keyHexString)) {
return identities.get(keyHexString);
}
return null;
}
public List<Message> getAllKnownMessages() {
List<Message> messageList = new ArrayList<>();
messageList.addAll(known);
return messageList;
}
}

View File

@ -123,6 +123,7 @@ public class MessageCodec extends ByteToMessageCodec<Message> {
loggerNet.info("RLPX protocol activated");
myKey = new ECKey().decompress();
channel.getShhHandler().setPrivKey(myKey);
byte[] nodeIdWithFormat = myKey.getPubKey();
nodeId = new byte[nodeIdWithFormat.length - 1];
System.arraycopy(nodeIdWithFormat, 1, nodeId, 0, nodeId.length);

View File

@ -1,66 +0,0 @@
package org.ethereum.serpent;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.BaseErrorListener;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.DiagnosticErrorListener;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.atn.PredictionMode;
import org.antlr.v4.runtime.misc.Nullable;
public class ParserUtils {
private ParserUtils() {
}
public static <L extends Lexer> L getLexer(Class<L> lexerClass, String source) {
CharStream input = new ANTLRInputStream(source);
L lexer;
try {
lexer = lexerClass.getConstructor(CharStream.class).newInstance(input);
} catch (Exception e) {
throw new IllegalArgumentException("couldn't invoke lexer constructor", e);
}
lexer.addErrorListener(new AntlrFailureListener());
return lexer;
}
public static <P extends Parser> P getParser(Class<? extends Lexer> lexerClass, Class<P> parserClass, String
source) {
Lexer lexer = getLexer(lexerClass, source);
TokenStream tokens = new CommonTokenStream(lexer);
P parser;
try {
parser = parserClass.getConstructor(TokenStream.class).newInstance(tokens);
} catch (Exception e) {
throw new IllegalArgumentException("couldn't invoke parser constructor", e);
}
parser.getInterpreter().setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);
parser.removeErrorListeners(); // don't spit to stderr
parser.addErrorListener(new DiagnosticErrorListener());
parser.addErrorListener(new AntlrFailureListener());
return parser;
}
private static class AntlrFailureListener extends BaseErrorListener {
@Override
public void syntaxError(Recognizer<?, ?> recognizer, @Nullable Object offendingSymbol, int line,
int charPositionInLine, String msg, @Nullable RecognitionException e) {
throw new AntlrParseException(line, charPositionInLine, msg, e);
}
}
public static class AntlrParseException extends RuntimeException {
public AntlrParseException(int line, int posInLine, String msg, Throwable cause) {
// posInLine comes in 0-indexed, but we want to 1-index it so it lines up with what editors say (they
// tend to 1-index)
super(String.format("at line %d column %d: %s", line, posInLine + 1, msg), cause);
}
}
}

View File

@ -1,227 +0,0 @@
package org.ethereum.serpent;
import org.ethereum.util.ByteUtil;
import org.ethereum.vm.OpCode;
import org.antlr.v4.runtime.tree.ParseTree;
import org.spongycastle.util.Arrays;
import org.spongycastle.util.BigIntegers;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author Roman Mandeleil
* @since 13.05.14
*/
public class SerpentCompiler {
public static String compile(String code) {
SerpentParser parser = ParserUtils.getParser(SerpentLexer.class, SerpentParser.class,
code);
ParseTree tree = parser.parse();
String result = new SerpentToAssemblyCompiler().visit(tree);
result = result.replaceAll("\\s+", " ");
result = result.trim();
return result;
}
public static String compileFullNotion(String code) {
SerpentParser parser = ParserUtils.getParser(SerpentLexer.class,
SerpentParser.class, code);
ParseTree tree = parser.parse_init_code_block();
String result = new SerpentToAssemblyCompiler().visit(tree);
result = result.replaceAll("\\s+", " ");
result = result.trim();
return result;
}
public static byte[] compileFullNotionAssemblyToMachine(String code) {
byte[] initCode = compileAssemblyToMachine(extractInitBlock(code));
byte[] codeCode = compileAssemblyToMachine(extractCodeBlock(code));
return encodeMachineCodeForVMRun(codeCode, initCode);
}
public static String extractInitBlock(String code) {
String result = "";
Pattern pattern = Pattern.compile("\\[init (.*?) init\\]");
Matcher matcher = pattern.matcher(code);
if (matcher.find()) {
result = matcher.group(1);
}
return result;
}
public static String extractCodeBlock(String code) {
String result = "";
Pattern pattern = Pattern.compile("\\[code (.*?) code\\]");
Matcher matcher = pattern.matcher(code);
if (matcher.find()) {
result = matcher.group(1);
}
return result;
}
public static byte[] compileAssemblyToMachine(String code) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
String[] lexaArr = code.split("\\s+");
List<String> lexaList = new ArrayList<>();
Collections.addAll(lexaList, lexaArr);
// Encode push_n numbers
boolean skipping = false;
for (int i = 0; i < lexaList.size(); ++i) {
String lexa = lexaList.get(i);
{ // skipping the [asm asm] block
if (lexa.equals("asm]")) {
skipping = false;
lexaList.remove(i);
--i;
continue;
}
if (lexa.equals("[asm")) {
skipping = true;
lexaList.remove(i);
--i;
continue;
}
if (skipping)
continue;
}
if (OpCode.contains(lexa) ||
lexa.contains("REF_") ||
lexa.contains("LABEL_")) continue;
int bytesNum = ByteUtil.numBytes(lexa);
String num = lexaList.remove(i);
BigInteger bNum = new BigInteger(num);
byte[] bytes = BigIntegers.asUnsignedByteArray(bNum);
if (bytes.length == 0) bytes = new byte[]{0};
for (int j = bytes.length; j > 0; --j) {
lexaList.add(i, (bytes[j - 1] & 0xFF) + "");
}
lexaList.add(i, "PUSH" + bytesNum);
i = i + bytesNum;
}
// encode ref for 5 bytes
for (int i = 0; i < lexaList.size(); ++i) {
String lexa = lexaList.get(i);
if (!lexa.contains("REF_")) continue;
lexaList.add(i + 1, lexa);
lexaList.add(i + 2, lexa);
lexaList.add(i + 3, lexa);
lexaList.add(i + 4, lexa);
i += 4;
}
// calc label pos & remove labels
Map<String, Integer> labels = new HashMap<>();
for (int i = 0; i < lexaList.size(); ++i) {
String lexa = lexaList.get(i);
if (!lexa.contains("LABEL_")) continue;
String label = lexaList.remove(i);
String labelNum = label.split("LABEL_")[1];
int labelPos = i;
labels.put(labelNum, labelPos);
--i;
}
// encode all ref occurrence
for (int i = 0; i < lexaList.size(); ++i) {
String lexa = lexaList.get(i);
if (!lexa.contains("REF_")) continue;
String ref = lexaList.remove(i);
lexaList.remove(i);
lexaList.remove(i);
lexaList.remove(i);
lexaList.remove(i);
String labelNum = ref.split("REF_")[1];
Integer pos = labels.get(labelNum);
int bytesNum = ByteUtil.numBytes(pos.toString());
lexaList.add(i, pos.toString());
for (int j = 0; j < (4 - bytesNum); ++j)
lexaList.add(i, "0");
lexaList.add(i, "PUSH4");
++i;
}
for (String lexa : lexaList) {
if (OpCode.contains(lexa))
baos.write(OpCode.byteVal(lexa));
else {
// TODO: support for number more than one byte
baos.write(Integer.parseInt(lexa) & 0xFF);
}
}
// wrap plan
// 1) that is the code
// 2) need to wrap it with PUSH1 (codesize) PUSH1 (codestart) 000 CODECOPY 000 PUSH1 (codesize) _fURN
return baos.toByteArray();
}
/**
* Return encoded bytes.
*/
public static byte[] encodeMachineCodeForVMRun(byte[] code, byte[] init) {
if (code == null || code.length == 0) throw new RuntimeException("code can't be empty code: " + code);
int numBytes = ByteUtil.numBytes(code.length + "");
byte[] lenBytes = BigIntegers.asUnsignedByteArray(BigInteger.valueOf(code.length));
StringBuilder sb = new StringBuilder();
for (byte lenByte : lenBytes) {
sb.append(lenByte).append(" ");
}
// calc real code start position (after the init header)
int pos = 10 + numBytes * 2;
if (init != null) pos += init.length;
// @push_len @len PUSH1 @src_start PUSH1 0 CODECOPY @push_len @len 0 PUSH1 0 RETURN
String header = String.format("[asm %s %s PUSH1 %d PUSH1 0 CODECOPY %s %s PUSH1 0 RETURN asm]",
"PUSH" + numBytes, sb.toString(), pos, "PUSH" + numBytes, sb.toString());
byte[] headerMachine = compileAssemblyToMachine(header);
return init != null ? Arrays.concatenate(init, headerMachine, code) :
Arrays.concatenate(headerMachine, code);
}
}

View File

@ -1,778 +0,0 @@
package org.ethereum.serpent;
import org.ethereum.crypto.HashUtil;
import org.antlr.v4.runtime.misc.NotNull;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author Roman Mandeleil
* @since 05.05.14
*/
public class SerpentToAssemblyCompiler extends SerpentBaseVisitor<String> {
private int labelIndex = 0;
private List<String> vars = new ArrayList<>();
private Map<String, Integer> arraysSize = new HashMap<>();
private List<String> arraysIndex = new ArrayList<>();
@Override
public String visitParse(@NotNull SerpentParser.ParseContext ctx) {
String codeBlock = visit(ctx.block());
int memSize = vars.size() * 32 - (vars.size() > 0 ? 1 : 0);
String initMemCodeBlock = "";
if (!arraysSize.isEmpty() && vars.size() > 0)
initMemCodeBlock = String.format(" 0 %d MSTORE8 ", memSize);
if (memSize == 0)
codeBlock = codeBlock.replace("@vars_table@", "0");
else
codeBlock = codeBlock.replace("@vars_table@", memSize + 1 + "");
return initMemCodeBlock + codeBlock;
}
@Override
public String visitParse_init_code_block(@NotNull SerpentParser.Parse_init_code_blockContext ctx) {
String initBlock = visit(ctx.block(0));
int memSize = vars.size() * 32 - (vars.size() > 0 ? 1 : 0);
String initMemInitBlock = "";
if (!arraysSize.isEmpty() && vars.size() > 0)
initMemInitBlock = String.format(" 0 %d MSTORE8 ", memSize);
if (memSize == 0)
initBlock = initBlock.replace("@vars_table@", "0");
else
initBlock = initBlock.replace("@vars_table@", memSize + 1 + "");
vars.clear();
String codeBlock = visit(ctx.block(1));
memSize = vars.size() * 32 - (vars.size() > 0 ? 1 : 0);
if (memSize == 0)
codeBlock = codeBlock.replace("@vars_table@", "0");
else
codeBlock = codeBlock.replace("@vars_table@", memSize + 1 + "");
String initMemCodeBlock = "";
if (!arraysSize.isEmpty() && vars.size() > 0)
initMemCodeBlock = String.format(" 0 %d MSTORE8 ", memSize);
return String.format(" [init %s %s init] [code %s %s code] ", initMemInitBlock, initBlock,
initMemCodeBlock, codeBlock);
}
@Override
public String visitIf_elif_else_stmt(@NotNull SerpentParser.If_elif_else_stmtContext ctx) {
StringBuilder retCode = new StringBuilder();
int endOfStmtLabel = labelIndex++;
// if body
SerpentParser.BlockContext ifBlock = (SerpentParser.BlockContext) ctx.getChild(4);
String blockCode = visitBlock(ifBlock);
String ifCond = visitCondition(ctx.condition(0));
int nextLabel = labelIndex++;
// if_cond [NOT REF_X JUMPI] if_body [REF_Y JUMP LABEL_X] Y=total_end
retCode.append(ifCond).
append(" NOT REF_").append(nextLabel).append(" JUMPI ").
append(blockCode).
append("REF_").append(endOfStmtLabel).
append(" JUMP LABEL_").append(nextLabel).append(" ");
// traverse the children and find out all [elif] and [else] that exist
int count = ctx.condition().size();
// traverse all 'elif' statements
int i = 1; // define i here for 'else' option
for (; i < count; ++i) {
// if the condition much at the end jump out of the main if
// append to general retCode
// TODO: [NOT REF_X JUMPI] elif_body [REF_Y JUMP LABEL_X] Y=total_end
// TODO extract the condition and the body
nextLabel = labelIndex++;
// elif condition
String elifCond = visitCondition(ctx.condition(i));
// elif body
String elifBlockCode = visitBlock(ctx.block(i));
retCode.append(elifCond).
append(" NOT REF_").append(nextLabel).append(" JUMPI ").
append(elifBlockCode).
append("REF_").append(endOfStmtLabel).append(" JUMP LABEL_").
append(nextLabel).append(" ");
}
// check if there is 'else'
if (ctx.block(i) != null) {
// body
String elseBlockCode = visitBlock(ctx.block(i));
// append to general retCode
retCode.append(elseBlockCode);
}
// [LABEL_Y] Y = end of statement
retCode.append("LABEL_").append(endOfStmtLabel).append(" ");
return retCode.toString();
}
@Override
public String visitWhile_stmt(@NotNull SerpentParser.While_stmtContext ctx) {
int whileStartRef = labelIndex++;
int whileEndRef = labelIndex++;
// elif condition
SerpentParser.ConditionContext whileCondition = (SerpentParser.ConditionContext)
ctx.getChild(1);
// elif body
SerpentParser.BlockContext whileBlock = (SerpentParser.BlockContext)
ctx.getChild(4);
return String.format(" LABEL_%d %s NOT REF_%d JUMPI %s REF_%d JUMP LABEL_%d ",
whileStartRef, visitCondition(whileCondition), whileEndRef, visitBlock(whileBlock),
whileStartRef, whileEndRef);
}
@Override
public String visitBlock(@NotNull SerpentParser.BlockContext ctx) {
return super.visitBlock(ctx);
}
@Override
public String visitCondition(@NotNull SerpentParser.ConditionContext ctx) {
return super.visitCondition(ctx);
}
@Override
public String visitGet_var(@NotNull SerpentParser.Get_varContext ctx) {
String varName = ctx.VAR().toString();
int addr;
addr = vars.indexOf(varName);
if (addr == -1) {
throw new UnassignVarException(varName);
}
return String.format(" %d MLOAD ", addr * 32);
}
@Override
public String visitAssign(@NotNull SerpentParser.AssignContext ctx) {
String varName = ctx.VAR().toString();
// msg assigned has two arrays to calc
if (ctx.msg_func() != null) {
return visitMsg_func(ctx.msg_func(), varName);
} else if (ctx.arr_def() != null) {
// if it's an array the all management is different
String arrayCode = visitArr_def(ctx.arr_def());
// calc the pointer addr
int pos = getArraySize(arrayCode);
arraysSize.put(varName, pos);
arraysIndex.add(varName);
return arrayCode;
} else {
String expression = visitExpression(ctx.expression());
int addr = vars.indexOf(varName);
if (addr == -1) {
addr = vars.size();
vars.add(varName);
}
return String.format(" %s %d MSTORE ", expression, addr * 32);
}
}
@Override
public String visitContract_storage_load(@NotNull SerpentParser.Contract_storage_loadContext ctx) {
String operand0 = visitExpression(ctx.expression());
return String.format(" %s SLOAD ", operand0);
}
@Override
public String visitContract_storage_assign(@NotNull SerpentParser.Contract_storage_assignContext ctx) {
String operand0 = visitExpression(ctx.expression(0));
String operand1 = visitExpression(ctx.expression(1));
return String.format(" %s %s SSTORE ", operand1, operand0);
}
@Override
public String visitInt_val(@NotNull SerpentParser.Int_valContext ctx) {
if (ctx.OP_NOT() != null)
return visitExpression(ctx.expression()) + " NOT";
if (ctx.expression() != null)
return visitExpression(ctx.expression());
if (ctx.get_var() != null)
return visitGet_var(ctx.get_var());
if (ctx.hex_num() != null)
return hexStringToDecimalString(ctx.hex_num().getText());
if (ctx.special_func() != null)
return visitSpecial_func(ctx.special_func());
if (ctx.msg_data() != null)
return visitMsg_data(ctx.msg_data());
if (ctx.contract_storage_load() != null)
return visitContract_storage_load(ctx.contract_storage_load());
if (ctx.send_func() != null)
return visitSend_func(ctx.send_func());
if (ctx.array_retreive() != null)
return visitArray_retreive(ctx.array_retreive());
return ctx.INT().toString();
}
@Override
public String visitArr_def(@NotNull SerpentParser.Arr_defContext ctx) {
List<SerpentParser.Int_valContext> numElements = ctx.int_val();
int arraySize = numElements.size() * 32 + 32;
StringBuffer arrayInit = new StringBuffer();
int i = 32;
for (SerpentParser.Int_valContext int_val : ctx.int_val()) {
arrayInit.append(String.format(" DUP %d ADD %s SWAP MSTORE ", i, visit(int_val)));
i += 32;
}
return String.format(" MSIZE 32 ADD MSIZE %s %d SWAP MSTORE ", arrayInit, arraySize);
}
@Override
public String visitArray_assign(@NotNull SerpentParser.Array_assignContext ctx) {
int order = this.arraysIndex.indexOf(ctx.VAR().toString());
if (order == -1) {
throw new Error("array with that name was not defined");
}
//calcAllocatedBefore();
int allocSize = 0;
for (int i = 0; i < order; ++i) {
String var = arraysIndex.get(i);
allocSize += arraysSize.get(var);
}
String index = visit(ctx.int_val());
String assignValue = visit(ctx.expression());
return String.format(" %s 32 %s MUL 32 ADD %d ADD @vars_table@ ADD MSTORE ", assignValue, index, allocSize);
}
@Override
public String visitArray_retreive(@NotNull SerpentParser.Array_retreiveContext ctx) {
int order = this.arraysIndex.indexOf(ctx.VAR().toString());
if (order == -1) {
throw new Error("array with that name was not defined");
}
int allocSize = 32;
for (int i = 0; i < order; ++i) {
String var = arraysIndex.get(i);
allocSize += arraysSize.get(var);
}
String index = visit(ctx.int_val());
return String.format(" 32 %s MUL %d ADD @vars_table@ ADD MLOAD ", index, allocSize);
}
@Override
public String visitMul_expr(@NotNull SerpentParser.Mul_exprContext ctx) {
if (ctx.mul_expr() == null) return visit(ctx.int_val());
String operand0 = visit(ctx.int_val());
String operand1 = visit(ctx.mul_expr());
switch (ctx.OP_MUL().getText().toLowerCase()) {
case "*":
return operand0 + " " + operand1 + " MUL";
case "/":
return operand0 + " " + operand1 + " DIV";
case "^":
return operand0 + " " + operand1 + " EXP";
case "%":
return operand0 + " " + operand1 + " MOD";
case "#/":
return operand0 + " " + operand1 + " SDIV";
case "#%":
return operand0 + " " + operand1 + " SMOD";
default:
throw new UnknownOperandException(ctx.OP_MUL().getText());
}
}
@Override
public String visitAdd_expr(@NotNull SerpentParser.Add_exprContext ctx) {
if (ctx.add_expr() == null) return visit(ctx.mul_expr());
String operand0 = visit(ctx.mul_expr());
String operand1 = visit(ctx.add_expr());
switch (ctx.OP_ADD().getText().toLowerCase()) {
case "+":
return operand0 + " " + operand1 + " ADD";
case "-":
return operand0 + " " + operand1 + " SUB";
default:
throw new UnknownOperandException(ctx.OP_ADD().getText());
}
}
@Override
public String visitRel_exp(@NotNull SerpentParser.Rel_expContext ctx) {
if (ctx.rel_exp() == null) return visit(ctx.add_expr());
String operand0 = visit(ctx.rel_exp());
String operand1 = visit(ctx.add_expr());
switch (ctx.OP_REL().getText().toLowerCase()) {
case "<":
return operand1 + " " + operand0 + " LT";
case ">":
return operand1 + " " + operand0 + " GT";
case ">=":
return operand1 + " " + operand0 + " LT NOT";
case "<=":
return operand1 + " " + operand0 + " GT NOT";
default:
throw new UnknownOperandException(ctx.OP_REL().getText());
}
}
@Override
public String visitEq_exp(@NotNull SerpentParser.Eq_expContext ctx) {
if (ctx.eq_exp() == null) return visit(ctx.rel_exp());
String operand0 = visit(ctx.rel_exp());
String operand1 = visit(ctx.eq_exp());
switch (ctx.OP_EQ().getText().toLowerCase()) {
case "==":
return operand0 + " " + operand1 + " EQ";
case "!=":
return operand0 + " " + operand1 + " EQ NOT";
default:
throw new UnknownOperandException(ctx.OP_EQ().getText());
}
}
@Override
public String visitAnd_exp(@NotNull SerpentParser.And_expContext ctx) {
if (ctx.and_exp() == null) return visit(ctx.eq_exp());
String operand0 = visit(ctx.eq_exp());
String operand1 = visit(ctx.and_exp());
switch (ctx.OP_AND().getText().toLowerCase()) {
case "&":
return operand0 + " " + operand1 + " AND";
default:
throw new UnknownOperandException(ctx.OP_AND().getText());
}
}
@Override
public String visitEx_or_exp(@NotNull SerpentParser.Ex_or_expContext ctx) {
if (ctx.ex_or_exp() == null) return visit(ctx.and_exp());
String operand0 = visit(ctx.and_exp());
String operand1 = visit(ctx.ex_or_exp());
switch (ctx.OP_EX_OR().getText().toLowerCase()) {
case "xor":
return operand0 + " " + operand1 + " XOR";
default:
throw new UnknownOperandException(ctx.OP_EX_OR().getText());
}
}
@Override
public String visitIn_or_exp(@NotNull SerpentParser.In_or_expContext ctx) {
if (ctx.in_or_exp() == null) return visit(ctx.ex_or_exp());
String operand0 = visit(ctx.ex_or_exp());
String operand1 = visit(ctx.in_or_exp());
switch (ctx.OP_IN_OR().getText().toLowerCase()) {
case "|":
return operand0 + " " + operand1 + " OR";
default:
throw new UnknownOperandException(ctx.OP_IN_OR().getText());
}
}
@Override
public String visitLog_and_exp(@NotNull SerpentParser.Log_and_expContext ctx) {
if (ctx.log_and_exp() == null) return visit(ctx.in_or_exp());
String operand0 = visit(ctx.in_or_exp());
String operand1 = visit(ctx.log_and_exp());
switch (ctx.OP_LOG_AND().getText().toLowerCase()) {
case "and":
return operand0 + " " + operand1 + " NOT NOT MUL";
case "&&":
return operand0 + " " + operand1 + " NOT NOT MUL";
default:
throw new UnknownOperandException(ctx.OP_LOG_AND().getText());
}
}
@Override
public String visitLog_or_exp(@NotNull SerpentParser.Log_or_expContext ctx) {
if (ctx.log_or_exp() == null) return visit(ctx.log_and_exp());
String operand0 = visit(ctx.log_and_exp());
String operand1 = visit(ctx.log_or_exp());
switch (ctx.OP_LOG_OR().getText().toLowerCase()) {
case "||":
return operand0 + " " + operand1 + " DUP 4 PC ADD JUMPI POP SWAP POP";
case "or":
return operand0 + " " + operand1 + " DUP 4 PC ADD JUMPI POP SWAP POP";
default:
throw new UnknownOperandException(ctx.OP_LOG_OR().getText());
}
}
@Override
public String visitMsg_sender(@NotNull SerpentParser.Msg_senderContext ctx) {
return "CALLER";
}
@Override
public String visitMsg_datasize(@NotNull SerpentParser.Msg_datasizeContext ctx) {
return "32 CALLDATASIZE DIV ";
}
@Override
public String visitMsg_value(@NotNull SerpentParser.Msg_valueContext ctx) {
return " CALLVALUE ";
}
@Override
public String visitContract_balance(@NotNull SerpentParser.Contract_balanceContext ctx) {
return " BALANCE ";
}
@Override
public String visitContract_address(@NotNull SerpentParser.Contract_addressContext ctx) {
return " ADDRESS ";
}
@Override
public String visitTx_origin(@NotNull SerpentParser.Tx_originContext ctx) {
return " ORIGIN ";
}
@Override
public String visitBlock_timestamp(@NotNull SerpentParser.Block_timestampContext ctx) {
return " TIMESTAMP ";
}
@Override
public String visitBlock_number(@NotNull SerpentParser.Block_numberContext ctx) {
return " NUMBER ";
}
@Override
public String visitTx_gas(@NotNull SerpentParser.Tx_gasContext ctx) {
return " GAS ";
}
@Override
public String visitBlock_difficulty(@NotNull SerpentParser.Block_difficultyContext ctx) {
return " DIFFICULTY ";
}
@Override
public String visitBlock_coinbase(@NotNull SerpentParser.Block_coinbaseContext ctx) {
return " COINBASE ";
}
@Override
public String visitTx_gasprice(@NotNull SerpentParser.Tx_gaspriceContext ctx) {
return " GASPRICE ";
}
@Override
public String visitBlock_prevhash(@NotNull SerpentParser.Block_prevhashContext ctx) {
return " PREVHASH ";
}
@Override
public String visitBlock_gaslimit(@NotNull SerpentParser.Block_gaslimitContext ctx) {
return " GASLIMIT ";
}
@Override
public String visitRet_func_1(@NotNull SerpentParser.Ret_func_1Context ctx) {
String operand0 = visit(ctx.expression());
return String.format(" %s MSIZE SWAP MSIZE MSTORE 32 SWAP RETURN ", operand0);
}
@Override
public String visitRet_func_2(@NotNull SerpentParser.Ret_func_2Context ctx) {
String operand0 = visit(ctx.expression(0));
String operand1 = visit(ctx.expression(1));
return String.format(" %s 32 MUL %s RETURN ", operand1, operand0);
}
@Override
public String visitSuicide_func(@NotNull SerpentParser.Suicide_funcContext ctx) {
String operand0 = visit(ctx.expression());
return String.format(" %s SUICIDE ", operand0);
}
@Override
public String visitStop_func(@NotNull SerpentParser.Stop_funcContext ctx) {
return " STOP ";
}
@Override
public String visitMsg_data(@NotNull SerpentParser.Msg_dataContext ctx) {
String operand0 = visit(ctx.expression());
return String.format("%s 32 MUL CALLDATALOAD ", operand0);
}
public String visitMsg_func(@NotNull SerpentParser.Msg_funcContext ctx, String varName) {
// msg_func: 'msg' '(' int_val ',' int_val ',' int_val ',' arr_def ',' int_val ',' int_val')' ;
// msg_func: 'msg' '(' [gas] ',' [to] ',' [value] ',' arr_def ',' [in_len] ',' [out_len]')' ;
String operand0 = visit(ctx.int_val(0));
String operand1 = visit(ctx.int_val(1));
String operand2 = visit(ctx.int_val(2));
String loadInData = visit(ctx.arr_def());
String inSizeCallParam = visit(ctx.int_val(3));
String outSizeCallParam = visit(ctx.int_val(4));
// TODO: 1. allocate out_memory and push ptr
// TODO: 2. push ptr for in_memory allocated
String randomArrayName = new String(HashUtil.randomPeerId());
int inSize = Integer.parseInt(inSizeCallParam);
int outSize = Integer.parseInt(outSizeCallParam);
arraysSize.put(randomArrayName, inSize * 32 + 32);
arraysIndex.add(randomArrayName);
int outSizeVal = outSize * 32 + 32;
arraysSize.put(varName, outSize * 32 + 32);
arraysIndex.add(varName);
// [OUTDATASIZE] [OUTDATASTART] [INDATASIZE] [INDATASTART] [VALUE] [TO] [GAS] CALL
// [OUTDATASIZE] [OUTDATASTART] [INDATASIZE] [INDATASTART] ***ARR_IN_SET*** [VALUE] [TO] [GAS] CALL
//X_X = [ 32 + 128 + 6 * 32 ] = [ var_table_size + in_arr_size + out_arr_size ]
// this code allocates the memory block for the out data,
// and saves the size in typical array format [size, element_1, element_2, ...]
String outArrSet = String.format(" %d MSIZE MSTORE 0 %d MSIZE ADD MSTORE8 ", outSizeVal, outSizeVal - 32);
return String.format("%d MSIZE %s %d %s %s %s %s CALL ",
outSizeVal, outArrSet, inSize * 32, loadInData, operand2, operand1, operand0);
}
@Override
public String visitSend_func(@NotNull SerpentParser.Send_funcContext ctx) {
String operand0 = visit(ctx.int_val(0));
String operand1 = visit(ctx.int_val(1));
String operand2 = visit(ctx.int_val(2));
// OUTDATASIZE OUTDATASTART INDATASIZE INDATASTART VALUE TO GAS CALL
return String.format("0 0 0 0 %s %s %s CALL ", operand2, operand1, operand0);
}
@Override
public String visitCreate_func(@NotNull SerpentParser.Create_funcContext ctx) {
String operand0 = visit(ctx.int_val(0));
String operand1 = visit(ctx.int_val(1));
String operand2 = visit(ctx.int_val(2));
// MEM_SIZE MEM_START GAS CREATE
return String.format(" %s %s %s CREATE ", operand2, operand1, operand0);
}
@Override
public String visitAsm(@NotNull SerpentParser.AsmContext ctx) {
int size = ctx.asm_symbol().getChildCount();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < size; ++i) {
String symbol = ctx.asm_symbol().children.get(i).toString();
symbol = symbol.trim();
// exclude all that is not an assembly code
if (symbol.equals("[asm") || symbol.equals("asm]") || symbol.equals("\n")) continue;
boolean match = Pattern.matches("[0-9]+", symbol);
if (match) {
int byteVal = Integer.parseInt(symbol);
if (byteVal > 255 || byteVal < 0)
throw new Error("In the [asm asm] block should be placed only byte range numbers");
}
match = Pattern.matches("0[xX][0-9a-fA-F]+", symbol);
if (match) {
int byteVal = Integer.parseInt(symbol.substring(2), 16);
if (byteVal > 255 || byteVal < 0)
throw new Error("In the [asm asm] block should be placed only byte range numbers");
symbol = byteVal + "";
}
sb.append(symbol).append(" ");
}
return "[asm " + sb.toString() + " asm]";
}
@Override
protected String aggregateResult(String aggregate, String nextResult) {
return aggregate + nextResult;
}
@Override
protected String defaultResult() {
return "";
}
/**
* @param hexNum should be in form '0x34fabd34....'
*/
private String hexStringToDecimalString(String hexNum) {
String digits = hexNum.substring(2);
if (digits.length() % 2 != 0) digits = "0" + digits;
byte[] numberBytes = Hex.decode(digits);
return (new BigInteger(1, numberBytes)).toString();
}
public static class UnknownOperandException extends RuntimeException {
public UnknownOperandException(String name) {
super("unknown operand: " + name);
}
}
public static class UnassignVarException extends RuntimeException {
public UnassignVarException(String name) {
super("attempt to access not assigned variable: " + name);
}
}
private static Integer getMsgOutputArraySize(String code) {
String result = "0";
Pattern pattern = Pattern.compile("<out_size ([0-9])* out_size>");
Matcher matcher = pattern.matcher(code.trim());
if (matcher.find()) {
String group = matcher.group(0);
result = group.replaceAll("<out_size ([0-9]*) out_size>", "$1").trim();
}
return Integer.parseInt(result);
}
private static Integer getMsgInputArraySize(String code) {
String result = "0";
Pattern pattern = Pattern.compile("<in_size ([0-9])* in_size>");
Matcher matcher = pattern.matcher(code.trim());
if (matcher.find()) {
String group = matcher.group(0);
result = group.replaceAll("<in_size ([0-9]*) in_size>", "$1").trim();
}
return Integer.parseInt(result);
}
private static String cleanMsgString(String code) {
return code.replaceAll("<(.*?)>", "");
}
/**
* After the array deff code is set
* extract the size out of code string
*/
private static Integer getArraySize(String code) {
String result = "0";
Pattern pattern = Pattern.compile(" [0-9]* SWAP MSTORE$");
Matcher matcher = pattern.matcher(code.trim());
if (matcher.find()) {
String group = matcher.group(0);
result = group.replace("SWAP MSTORE", "").trim();
}
return Integer.parseInt(result);
}
}

View File

@ -21,7 +21,7 @@ import static org.ethereum.util.Value.fromRlpEncoded;
*/
public class Cache {
private static final Logger gLogger = LoggerFactory.getLogger("general");
private static final Logger logger = LoggerFactory.getLogger("general");
private final KeyValueDataSource dataSource;
private Map<ByteArrayWrapper, Node> nodes = new ConcurrentHashMap<>();
@ -56,7 +56,7 @@ public class Cache {
if (node == null) {
byte[] data = this.dataSource.get(key);
node = new Node(fromRlpEncoded(data), false);
this.nodes.put(wrappedKey, node);
}
@ -80,10 +80,10 @@ public class Cache {
Map<byte[], byte[]> batch = new HashMap<>();
for (ByteArrayWrapper key : this.nodes.keySet()) {
Node node = this.nodes.get(key);
if (node.isDirty()) {
node.setDirty(false);
byte[] value = node.getValue().encode();
batch.put(key.getData(), value);
@ -96,10 +96,10 @@ public class Cache {
this.nodes.clear();
long finish = System.nanoTime();
float flushSize = (float) totalSize / 1048576;
float flushTime = (float) (finish - start) / 1_000_000;
gLogger.info(format("Flush state in: %02.2f ms, %d nodes, %02.2fMB", flushTime, batch.size(), flushSize));
logger.info(format("Flush state in: %02.2f ms, %d nodes, %02.2fMB", flushTime, batch.size(), flushSize));
}
public void undo() {

View File

@ -17,6 +17,7 @@ import static java.util.Arrays.copyOfRange;
import static org.ethereum.crypto.HashUtil.EMPTY_TRIE_HASH;
import static org.ethereum.util.ByteUtil.*;
import static org.ethereum.util.CompactEncoder.*;
import static org.ethereum.util.RLP.calcElementPrefixSize;
import static org.spongycastle.util.Arrays.concatenate;
/**
@ -519,7 +520,7 @@ public class TrieImpl implements Trie {
keysTotalSize += keyBytes.length;
byte[] valBytes = map.get(key).getValue().getData();
valsTotalSize += valBytes.length;
valsTotalSize += valBytes.length + calcElementPrefixSize(valBytes);
}
byte[] root = null;
@ -568,7 +569,7 @@ public class TrieImpl implements Trie {
k_1 += key.getData().length;
byte[] valBytes = map.get(key).getValue().getData();
byte[] valBytes = RLP.encodeElement( map.get(key).getValue().getData() );
System.arraycopy(valBytes, 0, rlpData,
listHeader.length + keysHeader.length + keysTotalSize + valsHeader.length + k_2,

View File

@ -1,6 +1,8 @@
package org.ethereum.util;
import org.ethereum.db.ByteArrayWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigInteger;
import java.nio.ByteBuffer;
@ -42,6 +44,9 @@ import static org.spongycastle.util.BigIntegers.asUnsignedByteArray;
*/
public class RLP {
private static final Logger logger = LoggerFactory.getLogger("rlp");
/**
* Allow for content up to size of 2^64 bytes *
*/
@ -477,6 +482,10 @@ public class RLP {
int pos = startPos;
while (pos < endPos) {
logger.debug("fullTraverse: level: " + level + " startPos: " + pos + " endPos: " + endPos);
// It's a list with a payload more than 55 bytes
// data[0] - 0xF7 = how many next bytes allocated
// for the length of the list
@ -749,7 +758,7 @@ public class RLP {
if (isNullOrZeroArray(srcData))
return new byte[]{(byte) OFFSET_SHORT_ITEM};
else if(isSingleZero(srcData))
else if (isSingleZero(srcData))
return new byte[]{00};
else if (srcData.length == 1 && (srcData[0] & 0xFF) < 0x80) {
return srcData;
@ -784,6 +793,31 @@ public class RLP {
}
}
public static int calcElementPrefixSize(byte[] srcData) {
if (isNullOrZeroArray(srcData))
return 0;
else if (isSingleZero(srcData))
return 0;
else if (srcData.length == 1 && (srcData[0] & 0xFF) < 0x80) {
return 0;
} else if (srcData.length < SIZE_THRESHOLD) {
return 1;
} else {
// length of length = BX
// prefix = [BX, [length]]
int tmpLength = srcData.length;
byte byteNum = 0;
while (tmpLength != 0) {
++byteNum;
tmpLength = tmpLength >> 8;
}
return 1 + byteNum;
}
}
public static byte[] encodeListHeader(int size) {
if (size == 0) {
@ -828,9 +862,9 @@ public class RLP {
if (length < SIZE_THRESHOLD) {
if (length == 0)
return new byte[] {(byte)0x80};
return new byte[]{(byte) 0x80};
else
return new byte[] {(byte)(0x80 + length)};
return new byte[]{(byte) (0x80 + length)};
} else {
@ -857,11 +891,11 @@ public class RLP {
}
}
public static byte[] encodeSet(Set<ByteArrayWrapper> data){
public static byte[] encodeSet(Set<ByteArrayWrapper> data) {
int dataLength = 0;
Set<byte[]> encodedElements = new HashSet<>();
for (ByteArrayWrapper element : data){
for (ByteArrayWrapper element : data) {
byte[] encodedElement = RLP.encodeElement(element.getData());
dataLength += encodedElement.length;
@ -875,7 +909,7 @@ public class RLP {
System.arraycopy(listHeader, 0, output, 0, listHeader.length);
int cummStart = listHeader.length;
for (byte[] element : encodedElements){
for (byte[] element : encodedElements) {
System.arraycopy(element, 0, output, cummStart, element.length);
cummStart += element.length;
}
@ -973,5 +1007,4 @@ public class RLP {
}
}
}

View File

@ -19,15 +19,28 @@ public class Value {
private byte[] rlp;
private byte[] sha3;
private boolean decoded = false;
public static Value fromRlpEncoded(byte[] data) {
if (data != null && data.length != 0) {
return new Value(RLP.decode(data, 0).getDecoded());
Value v = new Value();
v.init(data);
return v;
}
return null;
}
public Value(){
}
public void init(byte[] rlp){
this.rlp = rlp;
}
public Value(Object obj) {
this.decoded = true;
if (obj == null) return;
if (obj instanceof Value) {
@ -42,15 +55,18 @@ public class Value {
* *****************/
public Object asObj() {
decode();
return value;
}
public List<Object> asList() {
decode();
Object[] valueArray = (Object[]) value;
return Arrays.asList(valueArray);
}
public int asInt() {
decode();
if (isInt()) {
return (Integer) value;
} else if (isBytes()) {
@ -60,6 +76,7 @@ public class Value {
}
public long asLong() {
decode();
if (isLong()) {
return (Long) value;
} else if (isBytes()) {
@ -69,10 +86,12 @@ public class Value {
}
public BigInteger asBigInt() {
decode();
return (BigInteger) value;
}
public String asString() {
decode();
if (isBytes()) {
return new String((byte[]) value);
} else if (isString()) {
@ -82,6 +101,7 @@ public class Value {
}
public byte[] asBytes() {
decode();
if (isBytes()) {
return (byte[]) value;
} else if (isString()) {
@ -122,6 +142,13 @@ public class Value {
* Utility
* *****************/
public void decode(){
if (!this.decoded) {
this.value = RLP.decode(rlp, 0).getDecoded();
this.decoded = true;
}
}
public byte[] encode() {
if (rlp == null)
rlp = RLP.encode(value);
@ -143,32 +170,39 @@ public class Value {
* *****************/
public boolean isList() {
decode();
return value != null && value.getClass().isArray() && !value.getClass().getComponentType().isPrimitive();
}
public boolean isString() {
decode();
return value instanceof String;
}
public boolean isInt() {
decode();
return value instanceof Integer;
}
public boolean isLong() {
decode();
return value instanceof Long;
}
public boolean isBigInt() {
decode();
return value instanceof BigInteger;
}
public boolean isBytes() {
decode();
return value instanceof byte[];
}
// it's only if the isBytes() = true;
public boolean isReadableString() {
decode();
int readableChars = 0;
byte[] data = (byte[]) value;
@ -186,6 +220,7 @@ public class Value {
// it's only if the isBytes() = true;
public boolean isHexString() {
decode();
int hexChars = 0;
byte[] data = (byte[]) value;
@ -200,14 +235,17 @@ public class Value {
}
public boolean isHashCode() {
decode();
return this.asBytes().length == 32;
}
public boolean isNull() {
decode();
return value == null;
}
public boolean isEmpty() {
decode();
if (isNull()) return true;
if (isBytes() && asBytes().length == 0) return true;
if (isList() && asList().isEmpty()) return true;
@ -217,6 +255,7 @@ public class Value {
}
public int length() {
decode();
if (isList()) {
return asList().size();
} else if (isBytes()) {
@ -229,6 +268,7 @@ public class Value {
public String toString() {
decode();
StringBuilder stringBuilder = new StringBuilder();
if (isList()) {
@ -296,7 +336,7 @@ public class Value {
}
public int countBranchNodes() {
decode();
if (this.isList()) {
List<Object> objList = this.asList();
int i = 0;

View File

@ -360,8 +360,6 @@ public class Program {
Program program = new Program(programCode, programInvoke);
vm.play(program);
result = program.getResult();
this.result.addDeleteAccounts(result.getDeleteAccounts());
this.result.addLogInfos(result.getLogInfoList());
}
if (result.getException() != null) {
@ -394,6 +392,8 @@ public class Program {
}
track.commit();
this.result.addDeleteAccounts(result.getDeleteAccounts());
this.result.addLogInfos(result.getLogInfoList());
// IN SUCCESS PUSH THE ADDRESS INTO THE STACK
stackPush(new DataWord(newAddress));

View File

@ -1,6 +1,5 @@
# Root logger option
log4j.rootLogger=DEBUG, stdout, file
log4j.logger.dump=TRACE, DUMP
# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
@ -9,16 +8,12 @@ log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{HH:mm:ss.SSS} [%c{1}] %m%n
log4j.appender.stdout.Threshold=INFO
# Direct log messages to stdout
log4j.appender.DUMP=org.apache.log4j.ConsoleAppender
log4j.appender.DUMP.Target=System.out
log4j.appender.DUMP.layout=org.apache.log4j.PatternLayout
log4j.appender.file=org.apache.log4j.rolling.RollingFileAppender
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern= %d{HH:mm:ss} [%c{1}] %m%n
log4j.appender.file.RollingPolicy=org.apache.log4j.rolling.TimeBasedRollingPolicy
log4j.appender.file.RollingPolicy.FileNamePattern=./logs/ethereum_%d{yyyy-MM-dd}_h%d{HH}.log
log4j.appender.file.Threshold=ERROR
# filter noisy classes
log4j.logger.block = ERROR
@ -44,6 +39,8 @@ log4j.logger.gas = ERROR
log4j.logger.cli = ERROR
log4j.logger.TCK-Test = ERROR
log4j.logger.execute = ERROR
log4j.logger.rlp = ERROR
log4j.logger.org.springframework = ERROR
log4j.logger.org.hibernate = ERROR

View File

@ -185,7 +185,7 @@ root.hash.start = -1
peer.capabilities = eth, shh
# Key value data source values: [leveldb/redis/mapdb]
keyvalue.datasource = mapdb
keyvalue.datasource = leveldb
# Redis cloud enabled flag.
# Allows using RedisConnection for creating cloud based data structures.
@ -198,8 +198,10 @@ blockchain.only=false
# from a rlp lines
# file and not for
# the net
blocks.loader=
#E:\\temp\\_poc-9-blocks\\poc-9-492k_.dmp
#blocks.loader=E:\\temp\\_poc-9-blocks\\poc-9-blocks-start-476891.dmp
#blocks.loader=E:\\temp\\_poc-9-blocks\\poc-9-492k_.dmp
#blocks.loader=E:\\temp\\_poc-9-blocks\\poc-9-st-530k.dmp
#blocks.loader=E:\\temp\\_poc-9-blocks\\poc-9-619k.dmp
flush.batch.size=5000
flush.batch.size=10000
flush.ignore.consensus=false

View File

@ -89,11 +89,11 @@ public class BlockTest {
JSONParser parser = new JSONParser();
JSONObject genesisMap = (JSONObject) parser.parse(TEST_GENESIS);
Set<String> keys = genesisMap.keySet();
Set keys = genesisMap.keySet();
Trie state = new SecureTrie(null);
for (String key : keys) {
for (Object key : keys) {
JSONObject val = (JSONObject) genesisMap.get(key);
String denom = (String) val.keySet().toArray()[0];
@ -102,7 +102,7 @@ public class BlockTest {
BigInteger wei = Denomination.valueOf(denom.toUpperCase()).value().multiply(new BigInteger(value));
AccountState acctState = new AccountState(BigInteger.ZERO, wei);
state.update(Hex.decode(key), acctState.getEncoded());
state.update(Hex.decode(key.toString()), acctState.getEncoded());
}
logger.info("root: " + Hex.toHexString(state.getRootHash()));

View File

@ -151,69 +151,5 @@ public class ContractDetailsTest {
Hex.toHexString(contractDetails_.get(new DataWord(key_13)).getData()));
}
@Test @Ignore("cause it's heavy")
public void test___1() throws URISyntaxException, IOException {
// 13dc5836cd5638d0b81a1ba8377a7852d41b5bbe: saved on #490281
// found on block: #501570
// account.getStateRoot = d7b597b334b78c63ddf7beafc96484f5604472c40d438ea514882fab0813f074
// (!!!) next step is to find out why on #501595 the root changes
URL scenario_ = ClassLoader
.getSystemResource("rlp/contract-on-501570.rlp");
URL scenario1 = ClassLoader
.getSystemResource("rlp/contract-on-505829.rlp");
File file = new File(scenario1.toURI());
List<String> strData = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
String rlpString = strData.get(0);
byte[] rlp = Hex.decode(rlpString);
ContractDetailsImpl contractDetails = new ContractDetailsImpl(rlp);
File file_ = new File(scenario_.toURI());
List<String> strData_ = Files.readAllLines(file_.toPath(), StandardCharsets.UTF_8);
String rlpString_ = strData_.get(0);
byte[] rlp_ = Hex.decode(rlpString_);
ContractDetailsImpl contractDetails_ = new ContractDetailsImpl(rlp_);
contractDetails.put(new DataWord("5df1567644a3c48bf9a1b9d2e185cb9731053ab04882571d2d46c27935d11f1d"),
new DataWord("0000000000000000000000000000000000000000000000000000000000000000"));
System.out.println(Hex.toHexString(contractDetails.getStorageHash()));
// contractDetails.getStorage();
byte[] rlp_after = contractDetails.getEncoded();
ContractDetailsImpl contractDetails2 = new ContractDetailsImpl(rlp_after);
String root2 = Hex.toHexString(contractDetails2.getStorageHash());
System.out.println(root2);
byte[] rlp_after_2 = contractDetails2.getEncoded();
ContractDetailsImpl contractDetails3 = new ContractDetailsImpl(rlp_after_2);
String root3 = Hex.toHexString(contractDetails3.getStorageHash());
System.out.println(root3);
Set<DataWord> keys = contractDetails_.getStorage().keySet();
System.out.println( Hex.toHexString( contractDetails_.getStorageHash() ));
System.out.println( Hex.toHexString( contractDetails.getStorageHash() ));
for (DataWord key : keys){
DataWord val = contractDetails.get(key);
DataWord val_ = contractDetails_.get(key);
if (!val.equals(val_)) System.out.println(key + ":" + val);
}
}
}

View File

@ -0,0 +1,69 @@
package org.ethereum.net.shh;
import org.ethereum.crypto.ECKey;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
public class FilterTest {
byte[] to = new ECKey().decompress().getPubKey();
byte[] from = new ECKey().decompress().getPubKey();
String[] topics = {"topic1", "topic2", "topic3", "topic4"};
@Test
public void test1() {
Filter matcher = new Filter(null, null, new TopicMatcher(new String[]{}));
Filter message = new Filter(to, from, new TopicMatcher(topics));
assertTrue(matcher.match(message));
}
@Test
public void test2() {
Filter matcher = new Filter(to, null, new TopicMatcher(new String[]{}));
Filter message = new Filter(to, from, new TopicMatcher(topics));
assertTrue(matcher.match(message));
}
@Test
public void test3() {
Filter matcher = new Filter(to, null, new TopicMatcher(new String[]{}));
Filter message = new Filter(null, from, new TopicMatcher(topics));
assertTrue(!matcher.match(message));
}
@Test
public void test4() {
Filter matcher = new Filter(null, from, new TopicMatcher(new String[]{}));
Filter message = new Filter(to, from, new TopicMatcher(topics));
assertTrue(matcher.match(message));
}
@Test
public void test5() {
Filter matcher = new Filter(null, from, new TopicMatcher(new String[]{}));
Filter message = new Filter(to, null, new TopicMatcher(topics));
assertTrue(!matcher.match(message));
}
@Test
public void test6() {
Filter matcher = new Filter(null, from, new TopicMatcher(topics));
Filter message = new Filter(to, from, new TopicMatcher(topics));
assertTrue(matcher.match(message));
}
@Test
public void test7() {
Filter matcher = new Filter(null, null, new TopicMatcher(topics));
Filter message = new Filter(to, from, new TopicMatcher(new String[]{}));
assertTrue(!matcher.match(message));
}
}

View File

@ -3,7 +3,6 @@ package org.ethereum.net.shh;
import org.ethereum.crypto.ECKey;
import org.ethereum.util.RLP;
import org.ethereum.util.RLPList;
import org.junit.Before;
import org.junit.Test;
import java.math.BigInteger;
@ -14,14 +13,14 @@ import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
/**
* Created by kest on 6/13/15.
* @author by Konstantin Shabalin
*/
public class ShhTest {
private byte[] payload = "Hello whisper!".getBytes();
private ECKey privKey = ECKey.fromPrivate(BigInteger.TEN);
private byte[] pubKey = privKey.decompress().getPubKey();
private long ttl = 10000;
private int ttl = 10000;
private Topic[] topics = new Topic[]{
new Topic("topic 1"),
new Topic("topic 2"),
@ -32,7 +31,7 @@ public class ShhTest {
public void test1() {
Message sent = new Message(payload);
Options options = new Options(null, null, topics, ttl);
Envelope e = sent.wrap(0, options);
Envelope e = sent.wrap(Options.DEFAULT_POW, options);
RLPList rlpList = RLP.decode2(e.getEncoded());
RLPList.recursivePrint(rlpList);
@ -52,7 +51,7 @@ public class ShhTest {
public void test2() {
Message sent = new Message(payload);
Options options = new Options(privKey, null, topics, ttl);
Envelope e = sent.wrap(0, options);
Envelope e = sent.wrap(Options.DEFAULT_POW, options);
assertEquals(Hex.toHexString(e.getData()), Hex.toHexString(sent.getBytes()));
assertEquals(Hex.toHexString(sent.getPayload()), Hex.toHexString(payload));
@ -68,7 +67,7 @@ public class ShhTest {
public void test3() {
Message sent = new Message(payload);
Options options = new Options(null, pubKey, topics, ttl);
Envelope e = sent.wrap(0, options);
Envelope e = sent.wrap(Options.DEFAULT_POW, options);
assertEquals(Hex.toHexString(e.getData()), Hex.toHexString(sent.getBytes()));
assertNotEquals(Hex.toHexString(sent.getPayload()), Hex.toHexString(payload));
@ -86,7 +85,7 @@ public class ShhTest {
public void test4() {
Message sent = new Message(payload);
Options options = new Options(privKey, pubKey, topics, ttl);
Envelope e = sent.wrap(0, options);
Envelope e = sent.wrap(Options.DEFAULT_POW, options);
assertEquals(Hex.toHexString(e.getData()), Hex.toHexString(sent.getBytes()));
assertNotEquals(Hex.toHexString(sent.getPayload()), Hex.toHexString(payload));
@ -100,4 +99,6 @@ public class ShhTest {
assertEquals(Hex.toHexString(sent.getPayload()), Hex.toHexString(payload));
assertEquals(Hex.toHexString(pubKey), Hex.toHexString(recovered.decompress().getPubKey()));
}
}

View File

@ -0,0 +1,22 @@
package org.ethereum.net.shh;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
import static org.junit.Assert.assertEquals;
public class TopicTest {
@Test
public void test1(){
Topic topic = new Topic("cow");
assertEquals("c85ef7d7", Hex.toHexString(topic.getBytes()));
}
@Test
public void test2(){
Topic topic = new Topic("cowcowcow");
assertEquals("25068349", Hex.toHexString(topic.getBytes()));
}
}

View File

@ -18,6 +18,8 @@ import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertEquals;
/**
* @author Roman Mandeleil
* @since 15.10.2014
@ -39,61 +41,59 @@ public class AdaptiveMessageIdsTest {
@Test
public void test1() {
Assert.assertEquals(7, P2pMessageCodes.values().length);
assertEquals(7, P2pMessageCodes.values().length);
Assert.assertEquals(0, P2pMessageCodes.HELLO.asByte());
Assert.assertEquals(1, P2pMessageCodes.DISCONNECT.asByte());
Assert.assertEquals(2, P2pMessageCodes.PING.asByte());
Assert.assertEquals(3, P2pMessageCodes.PONG.asByte());
Assert.assertEquals(4, P2pMessageCodes.GET_PEERS.asByte());
Assert.assertEquals(5, P2pMessageCodes.PEERS.asByte());
Assert.assertEquals(15, P2pMessageCodes.USER.asByte());
assertEquals(0, P2pMessageCodes.HELLO.asByte());
assertEquals(1, P2pMessageCodes.DISCONNECT.asByte());
assertEquals(2, P2pMessageCodes.PING.asByte());
assertEquals(3, P2pMessageCodes.PONG.asByte());
assertEquals(4, P2pMessageCodes.GET_PEERS.asByte());
assertEquals(5, P2pMessageCodes.PEERS.asByte());
assertEquals(15, P2pMessageCodes.USER.asByte());
}
@Test
public void test2() {
Assert.assertEquals(9, EthMessageCodes.values().length);
assertEquals(8, EthMessageCodes.values().length);
Assert.assertEquals(0, EthMessageCodes.STATUS.asByte());
Assert.assertEquals(1, EthMessageCodes.GET_TRANSACTIONS.asByte());
Assert.assertEquals(2, EthMessageCodes.TRANSACTIONS.asByte());
Assert.assertEquals(3, EthMessageCodes.GET_BLOCK_HASHES.asByte());
Assert.assertEquals(4, EthMessageCodes.BLOCK_HASHES.asByte());
Assert.assertEquals(5, EthMessageCodes.GET_BLOCKS.asByte());
Assert.assertEquals(6, EthMessageCodes.BLOCKS.asByte());
Assert.assertEquals(7, EthMessageCodes.NEW_BLOCK.asByte());
Assert.assertEquals(8, EthMessageCodes.PACKET_COUNT.asByte());
assertEquals(0, EthMessageCodes.STATUS.asByte());
assertEquals(1, EthMessageCodes.GET_TRANSACTIONS.asByte());
assertEquals(2, EthMessageCodes.TRANSACTIONS.asByte());
assertEquals(3, EthMessageCodes.GET_BLOCK_HASHES.asByte());
assertEquals(4, EthMessageCodes.BLOCK_HASHES.asByte());
assertEquals(5, EthMessageCodes.GET_BLOCKS.asByte());
assertEquals(6, EthMessageCodes.BLOCKS.asByte());
assertEquals(7, EthMessageCodes.NEW_BLOCK.asByte());
EthMessageCodes.setOffset((byte) 0x10);
Assert.assertEquals(0x10 + 0, EthMessageCodes.STATUS.asByte());
Assert.assertEquals(0x10 + 1, EthMessageCodes.GET_TRANSACTIONS.asByte());
Assert.assertEquals(0x10 + 2, EthMessageCodes.TRANSACTIONS.asByte());
Assert.assertEquals(0x10 + 3, EthMessageCodes.GET_BLOCK_HASHES.asByte());
Assert.assertEquals(0x10 + 4, EthMessageCodes.BLOCK_HASHES.asByte());
Assert.assertEquals(0x10 + 5, EthMessageCodes.GET_BLOCKS.asByte());
Assert.assertEquals(0x10 + 6, EthMessageCodes.BLOCKS.asByte());
Assert.assertEquals(0x10 + 7, EthMessageCodes.NEW_BLOCK.asByte());
Assert.assertEquals(0x10 + 8, EthMessageCodes.PACKET_COUNT.asByte());
assertEquals(0x10 + 0, EthMessageCodes.STATUS.asByte());
assertEquals(0x10 + 1, EthMessageCodes.GET_TRANSACTIONS.asByte());
assertEquals(0x10 + 2, EthMessageCodes.TRANSACTIONS.asByte());
assertEquals(0x10 + 3, EthMessageCodes.GET_BLOCK_HASHES.asByte());
assertEquals(0x10 + 4, EthMessageCodes.BLOCK_HASHES.asByte());
assertEquals(0x10 + 5, EthMessageCodes.GET_BLOCKS.asByte());
assertEquals(0x10 + 6, EthMessageCodes.BLOCKS.asByte());
assertEquals(0x10 + 7, EthMessageCodes.NEW_BLOCK.asByte());
}
@Test
public void test3() {
Assert.assertEquals(5, ShhMessageCodes.values().length);
assertEquals(5, ShhMessageCodes.values().length);
Assert.assertEquals(0, ShhMessageCodes.STATUS.asByte());
Assert.assertEquals(1, ShhMessageCodes.MESSAGE.asByte());
Assert.assertEquals(2, ShhMessageCodes.ADD_FILTER.asByte());
Assert.assertEquals(3, ShhMessageCodes.REMOVE_FILTER.asByte());
Assert.assertEquals(4, ShhMessageCodes.PACKET_COUNT.asByte());
assertEquals(0, ShhMessageCodes.STATUS.asByte());
assertEquals(1, ShhMessageCodes.MESSAGE.asByte());
assertEquals(2, ShhMessageCodes.ADD_FILTER.asByte());
assertEquals(3, ShhMessageCodes.REMOVE_FILTER.asByte());
assertEquals(4, ShhMessageCodes.PACKET_COUNT.asByte());
ShhMessageCodes.setOffset((byte) 0x20);
Assert.assertEquals(0x20 + 0, ShhMessageCodes.STATUS.asByte());
Assert.assertEquals(0x20 + 1, ShhMessageCodes.MESSAGE.asByte());
Assert.assertEquals(0x20 + 2, ShhMessageCodes.ADD_FILTER.asByte());
Assert.assertEquals(0x20 + 3, ShhMessageCodes.REMOVE_FILTER.asByte());
Assert.assertEquals(0x20 + 4, ShhMessageCodes.PACKET_COUNT.asByte());
assertEquals(0x20 + 0, ShhMessageCodes.STATUS.asByte());
assertEquals(0x20 + 1, ShhMessageCodes.MESSAGE.asByte());
assertEquals(0x20 + 2, ShhMessageCodes.ADD_FILTER.asByte());
assertEquals(0x20 + 3, ShhMessageCodes.REMOVE_FILTER.asByte());
assertEquals(0x20 + 4, ShhMessageCodes.PACKET_COUNT.asByte());
}
@Test
@ -106,21 +106,20 @@ public class AdaptiveMessageIdsTest {
new Capability(Capability.SHH, ShhHandler.VERSION));
p2pHandler.adaptMessageIds(capabilities);
Assert.assertEquals(0x10 + 0, EthMessageCodes.STATUS.asByte());
Assert.assertEquals(0x10 + 1, EthMessageCodes.GET_TRANSACTIONS.asByte());
Assert.assertEquals(0x10 + 2, EthMessageCodes.TRANSACTIONS.asByte());
Assert.assertEquals(0x10 + 3, EthMessageCodes.GET_BLOCK_HASHES.asByte());
Assert.assertEquals(0x10 + 4, EthMessageCodes.BLOCK_HASHES.asByte());
Assert.assertEquals(0x10 + 5, EthMessageCodes.GET_BLOCKS.asByte());
Assert.assertEquals(0x10 + 6, EthMessageCodes.BLOCKS.asByte());
Assert.assertEquals(0x10 + 7, EthMessageCodes.NEW_BLOCK.asByte());
Assert.assertEquals(0x10 + 8, EthMessageCodes.PACKET_COUNT.asByte());
assertEquals(0x10 + 0, EthMessageCodes.STATUS.asByte());
assertEquals(0x10 + 1, EthMessageCodes.GET_TRANSACTIONS.asByte());
assertEquals(0x10 + 2, EthMessageCodes.TRANSACTIONS.asByte());
assertEquals(0x10 + 3, EthMessageCodes.GET_BLOCK_HASHES.asByte());
assertEquals(0x10 + 4, EthMessageCodes.BLOCK_HASHES.asByte());
assertEquals(0x10 + 5, EthMessageCodes.GET_BLOCKS.asByte());
assertEquals(0x10 + 6, EthMessageCodes.BLOCKS.asByte());
assertEquals(0x10 + 7, EthMessageCodes.NEW_BLOCK.asByte());
Assert.assertEquals(0x19 + 0, ShhMessageCodes.STATUS.asByte());
Assert.assertEquals(0x19 + 1, ShhMessageCodes.MESSAGE.asByte());
Assert.assertEquals(0x19 + 2, ShhMessageCodes.ADD_FILTER.asByte());
Assert.assertEquals(0x19 + 3, ShhMessageCodes.REMOVE_FILTER.asByte());
Assert.assertEquals(0x19 + 4, ShhMessageCodes.PACKET_COUNT.asByte());
assertEquals(0x18 + 0, ShhMessageCodes.STATUS.asByte());
assertEquals(0x18 + 1, ShhMessageCodes.MESSAGE.asByte());
assertEquals(0x18 + 2, ShhMessageCodes.ADD_FILTER.asByte());
assertEquals(0x18 + 3, ShhMessageCodes.REMOVE_FILTER.asByte());
assertEquals(0x18 + 4, ShhMessageCodes.PACKET_COUNT.asByte());
}
@Test // Capabilities should be read in alphabetical order
@ -133,20 +132,19 @@ public class AdaptiveMessageIdsTest {
new Capability(Capability.ETH, EthHandler.VERSION));
p2pHandler.adaptMessageIds(capabilities);
Assert.assertEquals(0x10 + 0, EthMessageCodes.STATUS.asByte());
Assert.assertEquals(0x10 + 1, EthMessageCodes.GET_TRANSACTIONS.asByte());
Assert.assertEquals(0x10 + 2, EthMessageCodes.TRANSACTIONS.asByte());
Assert.assertEquals(0x10 + 3, EthMessageCodes.GET_BLOCK_HASHES.asByte());
Assert.assertEquals(0x10 + 4, EthMessageCodes.BLOCK_HASHES.asByte());
Assert.assertEquals(0x10 + 5, EthMessageCodes.GET_BLOCKS.asByte());
Assert.assertEquals(0x10 + 6, EthMessageCodes.BLOCKS.asByte());
Assert.assertEquals(0x10 + 7, EthMessageCodes.NEW_BLOCK.asByte());
Assert.assertEquals(0x10 + 8, EthMessageCodes.PACKET_COUNT.asByte());
assertEquals(0x10 + 0, EthMessageCodes.STATUS.asByte());
assertEquals(0x10 + 1, EthMessageCodes.GET_TRANSACTIONS.asByte());
assertEquals(0x10 + 2, EthMessageCodes.TRANSACTIONS.asByte());
assertEquals(0x10 + 3, EthMessageCodes.GET_BLOCK_HASHES.asByte());
assertEquals(0x10 + 4, EthMessageCodes.BLOCK_HASHES.asByte());
assertEquals(0x10 + 5, EthMessageCodes.GET_BLOCKS.asByte());
assertEquals(0x10 + 6, EthMessageCodes.BLOCKS.asByte());
assertEquals(0x10 + 7, EthMessageCodes.NEW_BLOCK.asByte());
Assert.assertEquals(0x19 + 0, ShhMessageCodes.STATUS.asByte());
Assert.assertEquals(0x19 + 1, ShhMessageCodes.MESSAGE.asByte());
Assert.assertEquals(0x19 + 2, ShhMessageCodes.ADD_FILTER.asByte());
Assert.assertEquals(0x19 + 3, ShhMessageCodes.REMOVE_FILTER.asByte());
Assert.assertEquals(0x19 + 4, ShhMessageCodes.PACKET_COUNT.asByte());
assertEquals(0x18 + 0, ShhMessageCodes.STATUS.asByte());
assertEquals(0x18 + 1, ShhMessageCodes.MESSAGE.asByte());
assertEquals(0x18 + 2, ShhMessageCodes.ADD_FILTER.asByte());
assertEquals(0x18 + 3, ShhMessageCodes.REMOVE_FILTER.asByte());
assertEquals(0x18 + 4, ShhMessageCodes.PACKET_COUNT.asByte());
}
}

View File

@ -1,59 +0,0 @@
package org.ethereum.serpent;
import org.ethereum.serpent.SerpentCompiler;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
import static org.junit.Assert.assertEquals;
/**
* @author Roman Mandeleil
* @since 28.05.2014
*/
public class MachineCompileTest {
@Test // very simple contract
public void test1() {
String code = "a=2";
String expected = "6005600c60003960056000f36002600052";
String asm = SerpentCompiler.compile(code);
byte[] machineCode = SerpentCompiler.compileAssemblyToMachine(asm);
byte[] vmReadyCode = SerpentCompiler.encodeMachineCodeForVMRun(machineCode, null);
String result = Hex.toHexString(vmReadyCode);
assertEquals(expected, result);
}
@Test // contract for 256 bytes (len 2 bytes)
public void test2() {
String code = "a=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\na=2\n[asm PUSH10 asm]";
String expected = "610100600e6000396101006000f360026000526002600052600260005260026000526002600052600260005260026000526002600052600260005260026000526002600052600260005260026000526002600052600260005260026000526002600052600260005260026000526002600052600260005260026000526002600052600260005260026000526002600052600260005260026000526002600052600260005260026000526002600052600260005260026000526002600052600260005260026000526002600052600260005260026000526002600052600260005260026000526002600052600260005260026000526002600052600260005260026000526002600052600260005269";
String asm = SerpentCompiler.compile(code);
byte[] machineCode = SerpentCompiler.compileAssemblyToMachine(asm);
byte[] vmReadyCode = SerpentCompiler.encodeMachineCodeForVMRun(machineCode, null);
String result = Hex.toHexString(vmReadyCode);
assertEquals(expected, result);
}
@Test // contract for if jump
public void test3() {
String code = "a=2\n" +
"if a>0:\n" +
" b = 3\n" +
"else: \n" +
" c = 4";
// String expected = "610100600e6000396101006000f260026000546002600054600260005460026000546002600054600260005460026000546002600054600260005460026000546002600054600260005460026000546002600054600260005460026000546002600054600260005460026000546002600054600260005460026000546002600054600260005460026000546002600054600260005460026000546002600054600260005460026000546002600054600260005460026000546002600054600260005460026000546002600054600260005460026000546002600054600260005460026000546002600054600260005460026000546002600054600260005460026000546002600054600260005469";
String asm = SerpentCompiler.compile(code);
byte[] machineCode = SerpentCompiler.compileAssemblyToMachine(asm);
byte[] vmReadyCode = SerpentCompiler.encodeMachineCodeForVMRun(machineCode, null);
System.out.println(asm);
}
}

View File

@ -1397,6 +1397,11 @@ public class TrieTest {
String root2 = Hex.toHexString(trie2.getRootHash());
assertEquals("d7b597b334b78c63ddf7beafc96484f5604472c40d438ea514882fab0813f074", root2);
String dump1 = trie.getTrieDump();
String dump2 = trie2.getTrieDump();
assertEquals(dump1, dump2);
// bug that updates the value somewhere before 505k flush
trie2.update(Hex.decode("8c8998c70d860b06ebe80ce22500ec1192083a59ca111194cf2a7612d84b0e2a"), RLP.encodeElement(Hex.decode("0166")));
String root3 = Hex.toHexString(trie2.getRootHash());

View File

@ -141,8 +141,8 @@ root.hash.start = -1
# if set true, json tests will be loaded from local repository
GitHubTests.VMTest.loadLocal = false
# Key value data source values: [leveldb/redis]
keyvalue.datasource = leveldb
# Key value data source values: [leveldb/redis/mapdb]
keyvalue.datasource = mapdb
# structured trace
# is the trace being