Removed old tests.

This commit is contained in:
Adrian Tiberius 2015-06-01 21:17:58 +02:00
parent 5f8e8fe91d
commit 46a334e333
77 changed files with 26 additions and 15271 deletions

View File

@ -9,6 +9,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.ethereum.android.EthereumManager;
import org.ethereum.listener.EthereumListenerAdapter;
public class ConsoleFragment extends Fragment {

View File

@ -10,6 +10,8 @@ import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import org.ethereum.android.EthereumManager;
public class MainActivity extends ActionBarActivity {

View File

@ -4,6 +4,8 @@ import android.support.v4.app.FragmentManager;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentPagerAdapter;
import org.ethereum.android.EthereumManager;
public class TabsPagerAdapter extends FragmentPagerAdapter {
int tabsCount;

View File

@ -7,6 +7,8 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.ethereum.android.EthereumManager;
public class TestsFragment extends Fragment {
EthereumManager ethereumManager;

View File

@ -1,50 +0,0 @@
package org.ethereum.android;
import android.content.Context;
import org.ethereum.android.di.components.DaggerEthereumComponent;
import org.ethereum.android.di.modules.EthereumModule;
import org.ethereum.config.SystemProperties;
import org.ethereum.facade.Ethereum;
import org.ethereum.listener.EthereumListenerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class EthereumManager {
private static final Logger logger = LoggerFactory.getLogger("manager");
public static Ethereum ethereum = null;
public EthereumManager(Context context) {
System.setProperty("sun.arch.data.model", "32");
System.setProperty("leveldb.mmap", "false");
ethereum = DaggerEthereumComponent.builder()
.ethereumModule(new EthereumModule(context))
.build().ethereum();
}
public void start() {
}
public void connect() {
ethereum.connect(SystemProperties.CONFIG.activePeerIP(),
SystemProperties.CONFIG.activePeerPort(),
SystemProperties.CONFIG.activePeerNodeid());
//ethereum.getBlockchain();
}
public void startPeerDiscovery() {
ethereum.startPeerDiscovery();
}
public void addListener(EthereumListenerAdapter listener) {
ethereum.addListener(listener);
}
}

View File

@ -1,146 +0,0 @@
package org.ethereum.android.datasource;
import org.ethereum.config.SystemProperties;
import org.ethereum.datasource.KeyValueDataSource;
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.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 android.content.Context;
/**
* @author Roman Mandeleil
* @since 18.01.2015
*/
public class LevelDbDataSource implements KeyValueDataSource {
private static final Logger logger = LoggerFactory.getLogger("db");
String name;
private DB db;
private Context context;
public LevelDbDataSource() {
}
public LevelDbDataSource(String name) {
this.name = name;
}
public void setContext(Context context) {
this.context = context;
}
@Override
public void init() {
if (name == null) throw new NullPointerException("no name set to the db");
Options options = new Options();
options.createIfMissing(true);
options.compressionType(CompressionType.NONE);
org.iq80.leveldb.Logger logger1 = new org.iq80.leveldb.Logger() {
public void log(String message) {
logger.debug(message);
}
};
options.logger(logger1);
try {
logger.debug("Opening database");
File dbLocation = context.getDir(SystemProperties.CONFIG.databaseDir(), 0);
File fileLocation = new File(dbLocation, name);
if (SystemProperties.CONFIG.databaseReset()) {
destroyDB(fileLocation);
}
logger.debug("Initializing new or existing database: '{}'", fileLocation.getAbsolutePath());
db = Iq80DBFactory.factory.open(fileLocation, options);
} catch (IOException ioe) {
logger.error(ioe.getMessage(), ioe);
throw new RuntimeException("Can't initialize database");
}
}
public void destroyDB(File fileLocation) {
logger.debug("Destroying existing database");
Options options = new Options();
try {
Iq80DBFactory.factory.destroy(fileLocation, options);
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public byte[] get(byte[] key) {
return db.get(key);
}
@Override
public byte[] put(byte[] key, byte[] value) {
db.put(key, value);
return value;
}
@Override
public void delete(byte[] key) {
db.delete(key);
}
@Override
public Set<byte[]> keys() {
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;
}
@Override
public void updateBatch(Map<byte[], byte[]> rows) {
WriteBatch batch = db.createWriteBatch();
for (Map.Entry<byte[], byte[]> row : rows.entrySet())
batch.put(row.getKey(), row.getValue());
db.write(batch);
}
@Override
public void close() {
try {
logger.info("Close db: {}", name);
db.close();
} catch (IOException e) {
logger.error("Failed to find the db file on the close: {} ", name);
}
}
}

View File

@ -1,84 +0,0 @@
package org.ethereum.android.db;
import java.sql.SQLException;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;
import org.ethereum.db.BlockVO;
/**
* Database helper class used to manage the creation and upgrading of your database. This class also usually provides
* the DAOs used by the other classes.
*/
public class BlockDatabaseHelper extends OrmLiteSqliteOpenHelper {
private static final String DATABASE_NAME = "blocks.db";
private static final int DATABASE_VERSION = 1;
// the DAO object we use to access the SimpleData table
private Dao<BlockVO, Integer> blockDao = null;
public BlockDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
/**
* This is called when the database is first created. Usually you should call createTable statements here to create
* the tables that will store your data.
*/
@Override
public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource) {
try {
Log.i(BlockDatabaseHelper.class.getName(), "onCreate");
TableUtils.createTable(connectionSource, BlockVO.class);
} catch (SQLException e) {
Log.e(BlockDatabaseHelper.class.getName(), "Can't create database", e);
throw new RuntimeException(e);
}
}
/**
* This is called when your application is upgraded and it has a higher version number. This allows you to adjust
* the various data to match the new version number.
*/
@Override
public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int oldVersion, int newVersion) {
try {
Log.i(BlockDatabaseHelper.class.getName(), "onUpgrade");
TableUtils.dropTable(connectionSource, BlockVO.class, true);
// after we drop the old databases, we create the new ones
onCreate(db, connectionSource);
} catch (SQLException e) {
Log.e(BlockDatabaseHelper.class.getName(), "Can't drop databases", e);
throw new RuntimeException(e);
}
}
/**
* Returns the Database Access Object (DAO) for our SimpleData class. It will create it or just give the cached
* value.
*/
public Dao<BlockVO, Integer> getBlockDao() throws SQLException {
if (blockDao == null) {
blockDao = getDao(BlockVO.class);
}
return blockDao;
}
/**
* Close the database connections and clear any cached DAOs.
*/
@Override
public void close() {
super.close();
blockDao = null;
}
}

View File

@ -1,94 +0,0 @@
package org.ethereum.android.db;
import org.ethereum.core.Block;
import org.ethereum.core.TransactionReceipt;
import org.ethereum.db.BlockStore;
import org.ethereum.db.BlockVO;
import org.ethereum.util.ByteUtil;
import java.math.BigInteger;
import java.util.List;
public class BlockStoreImpl implements BlockStore {
private BlockDatabaseHelper blockDao;
private TransactionDatabaseHelper transactionDao;
public BlockStoreImpl(BlockDatabaseHelper blockDao, TransactionDatabaseHelper transactionDao) {
this.blockDao = blockDao;
this.transactionDao = transactionDao;
}
public byte[] getBlockHashByNumber(long blockNumber) {
Block block = getBlockByNumber(blockNumber);
if (block != null) return block.getHash();
return ByteUtil.EMPTY_BYTE_ARRAY;
}
public Block getBlockByNumber(long blockNumber) {
/*
List result = sessionFactory.getCurrentSession().
createQuery("from BlockVO where number = :number").
setParameter("number", blockNumber).list();
if (result.size() == 0) return null;
BlockVO vo = (BlockVO) result.get(0);
return new Block(vo.rlp);
*/
return null;
}
public Block getBlockByHash(byte[] hash) {
return null;
}
@SuppressWarnings("unchecked")
public List<byte[]> getListOfHashesStartFrom(byte[] hash, int qty) {
return null;
}
public void deleteBlocksSince(long number) {
}
public void saveBlock(Block block, List<TransactionReceipt> receipts) {
}
public BigInteger getTotalDifficultySince(long number) {
return null;
}
public BigInteger getTotalDifficulty() {
return null;
}
public Block getBestBlock() {
return null;
}
@SuppressWarnings("unchecked")
public List<Block> getAllBlocks() {
return null;
}
public void reset() {
}
public TransactionReceipt getTransactionReceiptByHash(byte[] hash) {
return null;
}
}

View File

@ -1,84 +0,0 @@
package org.ethereum.android.db;
import java.sql.SQLException;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;
import org.ethereum.db.TransactionReceiptVO;
/**
* Database helper class used to manage the creation and upgrading of your database. This class also usually provides
* the DAOs used by the other classes.
*/
public class TransactionDatabaseHelper extends OrmLiteSqliteOpenHelper {
private static final String DATABASE_NAME = "transactions.db";
private static final int DATABASE_VERSION = 1;
// the DAO object we use to access the SimpleData table
private Dao<TransactionReceiptVO, Integer> dao = null;
public TransactionDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
/**
* This is called when the database is first created. Usually you should call createTable statements here to create
* the tables that will store your data.
*/
@Override
public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource) {
try {
Log.i(BlockDatabaseHelper.class.getName(), "onCreate");
TableUtils.createTable(connectionSource, TransactionReceiptVO.class);
} catch (SQLException e) {
Log.e(BlockDatabaseHelper.class.getName(), "Can't create database", e);
throw new RuntimeException(e);
}
}
/**
* This is called when your application is upgraded and it has a higher version number. This allows you to adjust
* the various data to match the new version number.
*/
@Override
public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int oldVersion, int newVersion) {
try {
Log.i(BlockDatabaseHelper.class.getName(), "onUpgrade");
TableUtils.dropTable(connectionSource, TransactionReceiptVO.class, true);
// after we drop the old databases, we create the new ones
onCreate(db, connectionSource);
} catch (SQLException e) {
Log.e(BlockDatabaseHelper.class.getName(), "Can't drop databases", e);
throw new RuntimeException(e);
}
}
/**
* Returns the Database Access Object (DAO) for our SimpleData class. It will create it or just give the cached
* value.
*/
public Dao<TransactionReceiptVO, Integer> getBlockDao() throws SQLException {
if (dao == null) {
dao = getDao(TransactionReceiptVO.class);
}
return dao;
}
/**
* Close the database connections and clear any cached DAOs.
*/
@Override
public void close() {
super.close();
dao = null;
}
}

View File

@ -1,18 +0,0 @@
package org.ethereum.android.di.components;
import android.content.Context;
import org.ethereum.android.di.modules.EthereumModule;
import org.ethereum.facade.Ethereum;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules = EthereumModule.class)
public interface EthereumComponent {
Context context();
Ethereum ethereum();
}

View File

@ -1,170 +0,0 @@
package org.ethereum.android.di.modules;
import android.content.Context;
import org.ethereum.android.datasource.LevelDbDataSource;
import org.ethereum.config.SystemProperties;
import org.ethereum.core.BlockchainImpl;
import org.ethereum.core.Wallet;
import org.ethereum.db.BlockStore;
import org.ethereum.db.InMemoryBlockStore;
import org.ethereum.db.RepositoryImpl;
import org.ethereum.facade.Blockchain;
import org.ethereum.facade.Ethereum;
import org.ethereum.facade.EthereumImpl;
import org.ethereum.facade.Repository;
import org.ethereum.listener.CompositeEthereumListener;
import org.ethereum.listener.EthereumListener;
import org.ethereum.manager.AdminInfo;
import org.ethereum.manager.BlockLoader;
import org.ethereum.manager.WorldManager;
import org.ethereum.net.MessageQueue;
import org.ethereum.net.client.PeerClient;
import org.ethereum.net.eth.EthHandler;
import org.ethereum.net.p2p.P2pHandler;
import org.ethereum.net.peerdiscovery.DiscoveryChannel;
import org.ethereum.net.peerdiscovery.PeerDiscovery;
import org.ethereum.net.peerdiscovery.WorkerThread;
import org.ethereum.net.server.ChannelManager;
import org.ethereum.net.server.EthereumChannelInitializer;
import org.ethereum.net.shh.ShhHandler;
import org.ethereum.net.wire.MessageCodec;
import org.ethereum.vm.ProgramInvokeFactory;
import org.ethereum.vm.ProgramInvokeFactoryImpl;
import javax.inject.Provider;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class EthereumModule {
private Context context;
public EthereumModule(Context context) {
this.context = context;
}
@Provides
@Singleton
Ethereum provideEthereum(WorldManager worldManager, AdminInfo adminInfo, ChannelManager channelManager,
BlockLoader blockLoader, Provider<PeerClient> peerClientProvider, EthereumListener listener) {
return new EthereumImpl(worldManager, adminInfo, channelManager, blockLoader, peerClientProvider, listener);
}
@Provides
@Singleton
WorldManager provideWorldManager(Blockchain blockchain, Repository repository, Wallet wallet, PeerDiscovery peerDiscovery
,BlockStore blockStore, ChannelManager channelManager, AdminInfo adminInfo, EthereumListener listener) {
return new WorldManager(blockchain, repository, wallet, peerDiscovery, blockStore, channelManager, adminInfo, listener);
}
@Provides
@Singleton
Blockchain provideBlockchain(BlockStore blockStore, Repository repository,
Wallet wallet, AdminInfo adminInfo,
EthereumListener listener, ChannelManager channelManager) {
return new BlockchainImpl(blockStore, repository, wallet, adminInfo, listener, channelManager);
}
@Provides
@Singleton
BlockStore provideBlockStore() {
return new InMemoryBlockStore();
}
@Provides
@Singleton
Repository provideRepository() {
LevelDbDataSource detailsDS = new LevelDbDataSource();
detailsDS.setContext(context);
LevelDbDataSource stateDS = new LevelDbDataSource();
stateDS.setContext(context);
return new RepositoryImpl(detailsDS, stateDS);
}
@Provides
@Singleton
AdminInfo provideAdminInfo() {
return new AdminInfo();
}
@Provides
@Singleton
EthereumListener provideEthereumListener() {
return new CompositeEthereumListener();
}
@Provides
@Singleton
PeerDiscovery providePeerDiscovery() {
return new PeerDiscovery();
}
@Provides
@Singleton
ChannelManager provideChannelManager(EthereumListener listener) {
return new ChannelManager(listener);
}
@Provides
@Singleton
BlockLoader provideBlockLoader(Blockchain blockchain) {
return new BlockLoader(blockchain);
}
@Provides
@Singleton
ProgramInvokeFactory provideProgramInvokeFactory() {
return new ProgramInvokeFactoryImpl();
}
@Provides
EthHandler provideEthHandler(Blockchain blockchain, EthereumListener listener, Wallet wallet) {
return new EthHandler(blockchain, listener, wallet);
}
@Provides
ShhHandler provideShhHandler(EthereumListener listener) {
return new ShhHandler(listener);
}
@Provides
P2pHandler provideP2pHandler(PeerDiscovery peerDiscovery, EthereumListener listener) {
return new P2pHandler(peerDiscovery, listener);
}
@Provides
MessageCodec provideMessageCodec(EthereumListener listener) {
return new MessageCodec(listener);
}
@Provides
PeerClient providePeerClient(EthereumListener listener, ChannelManager channelManager,
Provider<EthereumChannelInitializer> ethereumChannelInitializerProvider) {
return new PeerClient(listener, channelManager, ethereumChannelInitializerProvider);
}
@Provides
MessageQueue provideMessageQueue(EthereumListener listener) {
return new MessageQueue(listener);
}
@Provides
WorkerThread provideWorkerThread(Provider<DiscoveryChannel> discoveryChannelProvider) {
return new WorkerThread(discoveryChannelProvider);
}
@Provides
String provideRemoteId() {
return SystemProperties.CONFIG.activePeerNodeid();
}
@Provides
@Singleton
Context provideContext() {
return context;
}
}

View File

@ -44,4 +44,5 @@ dependencies {
compile "com.j256.ormlite:ormlite-android:4.48"
compile "org.glassfish:javax.annotation:10.0-b28"
compile "org.iq80.leveldb:leveldb:0.7"
compile 'org.slf4j:slf4j-android:1.7.12'
}

View File

@ -42,11 +42,11 @@ public class TestRunner {
private boolean setNewStateRoot;
private String bestStateRoot;
@Inject
public ChannelManager channelManager;
@Inject
public TestRunner(ChannelManager channelManager) {
this.channelManager = channelManager;
public TestRunner() {
}
public List<String> runTestSuite(TestSuite testSuite) {
@ -58,7 +58,7 @@ public class TestRunner {
TestCase testCase = testIterator.next();
TestRunner runner = new TestRunner(channelManager);
TestRunner runner = new TestRunner();
List<String> result = runner.runTestCase(testCase);
resultCollector.addAll(result);
}

View File

@ -1,95 +0,0 @@
package test.ethereum;
import org.ethereum.config.SystemProperties;
import org.ethereum.facade.Ethereum;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.LocalSessionFactoryBuilder;
import java.sql.SQLException;
import java.util.Properties;
/**
* @author Roman Mandeleil
* @since 16.11.2014
*/
public class TestContext {
private static final Logger logger = LoggerFactory.getLogger("test");
@Bean
public SessionFactory sessionFactory() throws SQLException {
logger.info("loading context");
LocalSessionFactoryBuilder builder =
new LocalSessionFactoryBuilder(dataSource());
builder.scanPackages("org.ethereum.db")
.addProperties(getHibernateProperties());
return builder.buildSessionFactory();
}
private Properties getHibernateProperties() {
Properties prop = new Properties();
if (SystemProperties.CONFIG.databaseReset())
prop.put("hibernate.hbm2ddl.auto", "create");
prop.put("hibernate.format_sql", "true");
// todo: useful but annoying consider define by system.properties
// prop.put("hibernate.show_sql", "true");
prop.put("hibernate.dialect",
"org.hibernate.dialect.HSQLDialect");
return prop;
}
@Bean
public DataSourceTransactionManager transactionManager() {
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource());
return dataSourceTransactionManager;
}
@Bean(name = "dataSource")
public DriverManagerDataSource dataSource() {
logger.info("Connecting to the block store");
System.setProperty("hsqldb.reconfig_logging", "false");
String url =
String.format("jdbc:hsqldb:file:./%s/blockchain/blockchain.db;" +
"create=%s;hsqldb.default_table_type=cached",
SystemProperties.CONFIG.databaseDir(),
SystemProperties.CONFIG.databaseReset());
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("org.hsqldb.jdbcDriver");
ds.setUrl(url);
ds.setUsername("sa");
return ds;
}
@Autowired
Ethereum eth;
}

View File

@ -1,91 +0,0 @@
package test.ethereum.blockstore;
import org.ethereum.core.Block;
import org.ethereum.core.Genesis;
import org.ethereum.db.InMemoryBlockStore;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.List;
import static org.junit.Assert.*;
/**
* @author: Roman Mandeleil
* Created on: 30/01/2015 11:04
*/
public class InMemoryBlockStoreTest {
private static final Logger logger = LoggerFactory.getLogger("test");
private InMemoryBlockStore blockStore;
@Before
public void setup() throws URISyntaxException, IOException {
blockStore = new InMemoryBlockStore();
URL scenario1 = ClassLoader
.getSystemResource("blockstore/load.dmp");
File file = new File(scenario1.toURI());
List<String> strData = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
for (String blockRLP : strData) {
Block block = new Block(
Hex.decode(blockRLP));
logger.info("adding block.hash: {}", Hex.toHexString(block.getHash()).substring(6));
blockStore.saveBlock(block, null);
}
}
@Test
public void testSaving8001Blocks() {
Block bestBlock = blockStore.getBestBlock();
Long bestIndex = blockStore.getBestBlock().getNumber();
Long firstIndex = bestIndex - InMemoryBlockStore.MAX_BLOCKS;
assertTrue(bestIndex == 8001);
assertTrue(firstIndex == 7001);
assertTrue(blockStore.getBlockByNumber(7000) == null);
assertTrue(blockStore.getBlockByNumber(8002) == null);
Block byHashBlock = blockStore.getBlockByHash(bestBlock.getHash());
assertTrue(bestBlock.getNumber() == byHashBlock.getNumber());
byte[] hashFor8500 = blockStore.getBlockByNumber(7500).getHash();
Block block8500 = blockStore.getBlockByHash(hashFor8500);
assertTrue(block8500.getNumber() == 7500);
}
@Test
public void testListOfHashes(){
Block block = blockStore.getBlockByNumber(7500);
byte[] hash = block.getHash();
List<byte[]> hashes = blockStore.getListOfHashesStartFrom(hash, 700);
byte[] lastHash = hashes.get(hashes.size() - 1);
assertEquals(Hex.toHexString(blockStore.getBestBlock().getHash()),
Hex.toHexString(lastHash));
assertTrue(hashes.size() == 502);
}
}

View File

@ -1,25 +0,0 @@
package test.ethereum.core;
import org.ethereum.core.AccountState;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import static org.junit.Assert.assertEquals;
public class AccountStateTest {
@Test
public void testGetEncoded() {
String expected = "f85e809"
+ "a0100000000000000000000000000000000000000000000000000"
+ "a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
+ "a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470";
AccountState acct = new AccountState(BigInteger.ZERO, BigInteger.valueOf(2).pow(200));
assertEquals(expected, Hex.toHexString(acct.getEncoded()));
}
}

View File

@ -1,265 +0,0 @@
package test.ethereum.core;
import test.ethereum.TestContext;
import org.ethereum.config.SystemProperties;
import org.ethereum.core.Block;
import org.ethereum.core.BlockchainImpl;
import org.ethereum.core.Genesis;
import org.ethereum.facade.Blockchain;
import org.ethereum.manager.WorldManager;
import org.junit.After;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.List;
import static org.junit.Assert.*;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class BlockTest {
private static final Logger logger = LoggerFactory.getLogger("test");
@Configuration
@ComponentScan(basePackages = "org.ethereum")
static class ContextConfiguration extends TestContext {
static {
SystemProperties.CONFIG.setDataBaseDir("test_db/" + BlockTest.class);
}
}
@Autowired
WorldManager worldManager;
// https://ethereum.etherpad.mozilla.org/12
private String PoC7_GENESIS_HEX_RLP_ENCODED = "f9012ef90129a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0156df8ef53c723b40f97aff55dd785489cae8b457495916147687746bd5ee077a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b840000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080830f4240808080a004994f67dc55b09e814ab7ffc8df3686b4afb2bb53e60eae97ef043fe03fb829c0c0";
private String PoC7_GENESIS_HEX_HASH = "c9cb614fddd89b3bc6e2f0ed1f8e58e8a0d826612a607a6151be6f39c991a941";
private String PoC8_GENESIS_HEX_HASH = "32d9162f861a01bc8274e70b3cdb9d688fd7d8566f2f8c25cf1a882f244081c4";
String block_2 = "f8b5f8b1a0cf4b25b08b39350304fe12a16e4216c01a426f8f3dbf0d392b5b45"
+ "8ffb6a399da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a1"
+ "42fd40d493479476f5eabe4b342ee56b8ceba6ab2a770c3e2198e7a08a22d58b"
+ "a5c65b2bf660a961b075a43f564374d38bfe6cc69823eea574d1d16e80833fe0"
+ "04028609184e72a000830f3aab80845387c60380a00000000000000000000000"
+ "0000000000000000000000000033172b6669131179c0c0";
String block_17 = "f9016df8d3a0aa142573b355c6f2e8306471c869b0d12d0638cea3f57d39991a"
+ "b1b03ffa40daa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40"
+ "d4934794e559de5527492bcb42ec68d07df0742a98ec3f1ea031c973c20e7a15c319a9ff"
+ "9b0aab5bdc121320767fee71fb2b771ce1c93cf812a01b224ec310c2bfb40fd0e6a668ee"
+ "7c06a5a4a4bfb99620d0fea8f7b43315dd59833f3130118609184e72a000830f01ec8201"
+ "f4845387f36980a00000000000000000000000000000000000000000000000000532c3ae"
+ "9b3503f6f895f893f86d018609184e72a0008201f494f625565ac58ec5dadfce1b8f9fb1"
+ "dd30db48613b8862cf5246d0c80000801ca05caa26abb350e0521a25b8df229806f3777d"
+ "9e262996493846a590c7011697dba07bb7680a256ede4034212b7a1ae6c7caea73190cb0"
+ "7dedb91a07b72f34074e76a00cd22d78d556175604407dc6109797f5c8d990d05f1b352e"
+ "10c71b3dd74bc70f8201f4c0";
String block_32 = "f8f8f8f4a00a312c2b0a8f125c60a3976b6e508e740e095eb59943988d9bbfb8"
+ "aa43922e31a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4"
+ "934794e559de5527492bcb42ec68d07df0742a98ec3f1ea050188ab86bdf164ac90eb283"
+ "5a04a8930aae5393c3a2ef1166fb95028f9456b88080b840000000000000000000000000"
+ "000000000000000000000000000000000000000000000000000000000000000000000000"
+ "00000000000000000000000000000000833ee248208609184e72a000830eca0080845387"
+ "fd2080a00000000000000000000000000000000000000000000000001f52ebb192c4ea97"
+ "c0c0";
@After
public void doReset() {
worldManager.reset();
}
@Ignore
@Test /* got from go guy */
public void testGenesisFromRLP() {
// from RLP encoding
byte[] genesisBytes = Hex.decode(PoC7_GENESIS_HEX_RLP_ENCODED);
Block genesisFromRLP = new Block(genesisBytes);
Block genesis = Genesis.getInstance();
assertEquals(Hex.toHexString(genesis.getHash()), Hex.toHexString(genesisFromRLP.getHash()));
assertEquals(Hex.toHexString(genesis.getParentHash()), Hex.toHexString(genesisFromRLP.getParentHash()));
assertEquals(Hex.toHexString(genesis.getStateRoot()), Hex.toHexString(genesisFromRLP.getStateRoot()));
}
@Test
public void testGenesisFromNew() {
Block genesis = Genesis.getInstance();
logger.info(genesis.toString());
logger.info("genesis hash: [{}]", Hex.toHexString(genesis.getHash()));
logger.info("genesis rlp: [{}]", Hex.toHexString(genesis.getEncoded()));
assertEquals(PoC8_GENESIS_HEX_HASH, Hex.toHexString(genesis.getHash()));
// assertEquals(PoC7_GENESIS_HEX_RLP_ENCODED, Hex.toHexString(genesis.getEncoded()));
}
@Test /* block without transactions - block#32 in PoC5 cpp-chain */
public void testEmptyBlock() {
byte[] payload = Hex.decode(block_32);
Block blockData = new Block(payload);
logger.info(blockData.toString());
}
@Test /* block with single balance transfer transaction - block#17 in PoC5 cpp-chain */
@Ignore
public void testSingleBalanceTransfer() {
byte[] payload = Hex.decode(block_17); // todo: find out an uptodate block wire
Block blockData = new Block(payload);
logger.info(blockData.toString());
}
@Test /* large block with 5 transactions -block#1 in PoC5 cpp-chain */
public void testBlockWithContractCreation() {
byte[] payload = Hex.decode(PoC7_GENESIS_HEX_RLP_ENCODED);
Block block = new Block(payload);
logger.info(block.toString());
}
@Test
public void testCalcDifficulty() {
Blockchain blockchain = worldManager.getBlockchain();
Block genesis = Genesis.getInstance();
BigInteger difficulty = new BigInteger(1, genesis.calcDifficulty());
logger.info("Genesis difficulty: [{}]", difficulty.toString());
assertEquals(new BigInteger(1, Genesis.DIFFICULTY), difficulty);
// Storing genesis because the parent needs to be in the DB for calculation.
blockchain.add(genesis);
Block block1 = new Block(Hex.decode(PoC7_GENESIS_HEX_RLP_ENCODED));
BigInteger calcDifficulty = new BigInteger(1, block1.calcDifficulty());
BigInteger actualDifficulty = new BigInteger(1, block1.getDifficulty());
logger.info("Block#1 actual difficulty: [{}] ", actualDifficulty.toString());
logger.info("Block#1 calculated difficulty: [{}] ", calcDifficulty.toString());
assertEquals(actualDifficulty, calcDifficulty);
}
@Test
public void testCalcGasLimit() {
BlockchainImpl blockchain = (BlockchainImpl) worldManager.getBlockchain();
Block genesis = Genesis.getInstance();
long gasLimit = blockchain.calcGasLimit(genesis.getHeader());
logger.info("Genesis gasLimit: [{}] ", gasLimit);
assertEquals(Genesis.GAS_LIMIT, gasLimit);
// Test with block
Block block1 = new Block(Hex.decode(PoC7_GENESIS_HEX_RLP_ENCODED));
long calcGasLimit = blockchain.calcGasLimit(block1.getHeader());
long actualGasLimit = block1.getGasLimit();
blockchain.tryToConnect(block1);
logger.info("Block#1 actual gasLimit [{}] ", actualGasLimit);
logger.info("Block#1 calculated gasLimit [{}] ", calcGasLimit);
assertEquals(actualGasLimit, calcGasLimit);
}
@Ignore
@Test
public void testScenario1() throws URISyntaxException, IOException {
BlockchainImpl blockchain = (BlockchainImpl) worldManager.getBlockchain();
URL scenario1 = ClassLoader
.getSystemResource("blockload/scenario1.dmp");
File file = new File(scenario1.toURI());
List<String> strData = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
byte[] root = Genesis.getInstance().getStateRoot();
for (String blockRLP : strData) {
Block block = new Block(
Hex.decode(blockRLP));
logger.info("sending block.hash: {}", Hex.toHexString(block.getHash()));
blockchain.tryToConnect(block);
root = block.getStateRoot();
}
logger.info("asserting root state is: {}", Hex.toHexString(root));
//expected root: fb8be59e6420892916e3967c60adfdf48836af040db0072ca411d7aaf5663804
assertEquals(Hex.toHexString(root),
Hex.toHexString(worldManager.getRepository().getRoot()));
}
@Ignore
@Test
public void testScenario2() throws URISyntaxException, IOException {
BlockchainImpl blockchain = (BlockchainImpl) worldManager.getBlockchain();
URL scenario1 = ClassLoader
.getSystemResource("blockload/scenario2.dmp");
File file = new File(scenario1.toURI());
List<String> strData = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
byte[] root = Genesis.getInstance().getStateRoot();
for (String blockRLP : strData) {
Block block = new Block(
Hex.decode(blockRLP));
logger.info("sending block.hash: {}", Hex.toHexString(block.getHash()));
blockchain.tryToConnect(block);
root = block.getStateRoot();
}
logger.info("asserting root state is: {}", Hex.toHexString(root));
//expected root: a5e2a18bdbc4ab97775f44852382ff5585b948ccb15b1d69f0abb71e2d8f727d
assertEquals(Hex.toHexString(root),
Hex.toHexString(worldManager.getRepository().getRoot()));
}
@Test
@Ignore
public void testUncleValidGenerationGap() {
// TODO
fail("Not yet implemented");
}
@Test
@Ignore
public void testUncleInvalidGenerationGap() {
// TODO
fail("Not yet implemented");
}
@Test
@Ignore
public void testUncleInvalidParentGenerationGap() {
// TODO
fail("Not yet implemented");
}
}

View File

@ -1,56 +0,0 @@
package test.ethereum.core;
import org.ethereum.core.Bloom;
import org.ethereum.crypto.SHA3Helper;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
/**
* @author Roman Mandeleil
* @since 20.11.2014
*/
public class BloomTest {
@Test
public void test1() {
byte[] key = SHA3Helper.sha3(Hex.decode("CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826"));
Bloom bloom = Bloom.create(key);
System.out.println(bloom);
}
@Test
public void test2() {
byte[] key = Hex.decode("0954D2BEF0CA79C1A988AE5FF3072C2AEA90F3967A9596065123F2A15AA37EF3");
Bloom bloom = Bloom.create(key);
System.out.println(bloom);
}
@Test
public void test3() {
byte[] key = SHA3Helper.sha3(Hex.decode("22341AE42D6DD7384BC8584E50419EA3AC75B83F "));
Bloom bloom = Bloom.create(key);
System.out.println(bloom);
}
@Test
public void test4() {
byte[] key = SHA3Helper.sha3(Hex.decode("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6"));
Bloom bloom = Bloom.create(key);
System.out.println(bloom);
}
}

View File

@ -1,137 +0,0 @@
package test.ethereum.core;
import test.ethereum.TestContext;
import org.ethereum.config.SystemProperties;
import org.ethereum.core.Block;
import org.ethereum.core.BlockchainImpl;
import org.ethereum.core.Chain;
import org.ethereum.manager.WorldManager;
import org.junit.After;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.List;
import static junit.framework.TestCase.assertEquals;
/**
* @author Roman Mandeleil
* @since 09.11.2014
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ForkTest {
private static final Logger logger = LoggerFactory.getLogger("test");
@Configuration
@ComponentScan(basePackages = "org.ethereum")
static class ContextConfiguration extends TestContext {
static {
SystemProperties.CONFIG.setDataBaseDir("test_db/" + ForkTest.class);
}
}
@Autowired
WorldManager worldManager;
@After
public void doReset() {
worldManager.reset();
}
@Ignore
@Test
public void fork1() throws URISyntaxException, IOException {
BlockchainImpl blockchain = (BlockchainImpl) worldManager.getBlockchain();
URL scenario1 = ClassLoader
.getSystemResource("fork/scenario1.dmp");
File file = new File(scenario1.toURI());
List<String> strData = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
for (String blockRLP : strData) {
Block block = new Block(
Hex.decode(blockRLP));
logger.info("sending block.hash: {}", Hex.toHexString(block.getHash()));
blockchain.tryToConnect(block);
}
List<Chain> altChains = blockchain.getAltChains();
List<Block> garbage = blockchain.getGarbage();
assertEquals(1, altChains.size());
assertEquals(13, altChains.get(0).getSize());
assertEquals(20, blockchain.getSize());
assertEquals(0, garbage.size());
}
@Ignore
@Test
public void fork2() throws URISyntaxException, IOException {
BlockchainImpl blockchain = (BlockchainImpl) worldManager.getBlockchain();
URL scenario2 = ClassLoader
.getSystemResource("fork/scenario2.dmp");
File file = new File(scenario2.toURI());
List<String> strData = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
for (String blockRLP : strData) {
Block block = new Block(
Hex.decode(blockRLP));
logger.info("sending block.hash: {}", Hex.toHexString(block.getHash()));
blockchain.tryToConnect(block);
}
List<Chain> altChains = blockchain.getAltChains();
List<Block> garbage = blockchain.getGarbage();
assertEquals(2, altChains.size());
// assertEquals(13, altChains.get(0).getSize());
assertEquals(new BigInteger("13238272"), altChains.get(0).getTotalDifficulty());
assertEquals(new BigInteger("13369344"), altChains.get(1).getTotalDifficulty());
assertEquals(new BigInteger("13238272"), blockchain.getTotalDifficulty());
assertEquals(100, blockchain.getSize());
assertEquals(0, garbage.size());
System.out.println();
}
}

View File

@ -1,69 +0,0 @@
package test.ethereum.core;
import org.ethereum.vm.LogInfo;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import static org.junit.Assert.assertEquals;
/**
* @author Roman Mandeleil
* @since 05.12.2014
*/
public class LogInfoTest {
private static final Logger logger = LoggerFactory.getLogger("test");
@Test // rlp decode
public void test_1() {
// LogInfo{address=d5ccd26ba09ce1d85148b5081fa3ed77949417be, topics=[000000000000000000000000459d3a7595df9eba241365f4676803586d7d199c 436f696e73000000000000000000000000000000000000000000000000000000 ], data=}
byte[] rlp = Hex.decode("f85a94d5ccd26ba09ce1d85148b5081fa3ed77949417bef842a0000000000000000000000000459d3a7595df9eba241365f4676803586d7d199ca0436f696e7300000000000000000000000000000000000000000000000000000080");
LogInfo logInfo = new LogInfo(rlp);
assertEquals("d5ccd26ba09ce1d85148b5081fa3ed77949417be",
Hex.toHexString(logInfo.getAddress()));
assertEquals("", Hex.toHexString(logInfo.getData()));
assertEquals("000000000000000000000000459d3a7595df9eba241365f4676803586d7d199c",
logInfo.getTopics().get(0).toString());
assertEquals("436f696e73000000000000000000000000000000000000000000000000000000",
logInfo.getTopics().get(1).toString());
logger.info("{}", logInfo);
}
@Test // rlp decode
public void test_2() {
LogInfo log = new LogInfo(Hex.decode("d5ccd26ba09ce1d85148b5081fa3ed77949417be"), null, null);
assertEquals("d794d5ccd26ba09ce1d85148b5081fa3ed77949417bec080", Hex.toHexString(log.getEncoded()));
logger.info("{}", log);
}
@Test // rlp decode
public void test_3() {
// LogInfo{address=f2b1a404bcb6112a0ff2c4197cb02f3de40018b3, topics=[5a360139cff27713da0fe18a2100048a7ce1b7700c953a82bc3ff011437c8c2a 588d7ddcc06c14843ea68e690dfd4ec91ba09a8ada15c5b7fa6fead9c8befe4b ], data=}
byte[] rlp = Hex.decode("f85a94f2b1a404bcb6112a0ff2c4197cb02f3de40018b3f842a05a360139cff27713da0fe18a2100048a7ce1b7700c953a82bc3ff011437c8c2aa0588d7ddcc06c14843ea68e690dfd4ec91ba09a8ada15c5b7fa6fead9c8befe4b80");
LogInfo logInfo = new LogInfo(rlp);
assertEquals("f2b1a404bcb6112a0ff2c4197cb02f3de40018b3",
Hex.toHexString(logInfo.getAddress()));
assertEquals("00800000000000000010000000000000000000000000002000000000000000000012000000100000000050000020000000000000000000000000000000000000",
logInfo.getBloom().toString());
assertEquals("f85a94f2b1a404bcb6112a0ff2c4197cb02f3de40018b3f842a05a360139cff27713da0fe18a2100048a7ce1b7700c953a82bc3ff011437c8c2aa0588d7ddcc06c14843ea68e690dfd4ec91ba09a8ada15c5b7fa6fead9c8befe4b80",
Hex.toHexString(logInfo.getEncoded()));
logger.info("{}", logInfo);
}
}

View File

@ -1,125 +0,0 @@
package test.ethereum.core;
import org.ethereum.core.Block;
import org.ethereum.mine.Miner;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import static org.junit.Assert.*;
public class MinerTest {
private static final Logger logger = LoggerFactory.getLogger("test");
// Example block#32 from Poc5 chain - rlpEncoded without nonce
private String rlpWithoutNonce = "f894f890a00a312c2b0a8f125c60a3976b6e508e740e095eb59943988d9bbfb8"
+ "aa43922e31a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e559de5527492bcb42ec68d07df0742a98ec3f1ea050188ab86bdf164ac90eb2835a04a8930aae5393c3a2ef1166fb95028f9456b880833ee248208609184e72a000830eca0080845387fd2080c0c0";
@Test
@Ignore
public void testMine() {
boolean miningTestEnabled = false;
if (miningTestEnabled) {
Block block = createBlock(null);
assertEquals(rlpWithoutNonce, Hex.toHexString(block.getEncodedWithoutNonce()));
System.out.println("Searching for nonce of following block: \n" + block.toString());
Miner miner = new Miner();
boolean mined = miner.mine(block, block.getDifficulty());
assertTrue(mined);
boolean valid = block.validateNonce();
assertTrue(valid);
// expectedHash is the actual hash from block#32 in PoC5 chain based on nonce below
String expectedHash = "ce7201f6cc5eb1a6f35c7dda8acda111647a0f8a5bf0518e46579b03e29fe14b";
assertEquals(expectedHash, Hex.toHexString(block.getHash()));
// expectedNonce is the actual nonce from block#32 in Poc5 chain
String expectedNonce = "0000000000000000000000000000000000000000000000001f52ebb192c4ea97"; // from Poc5 chain
// Actual is "000000000000000000000000000000000000000000000000000000000098cc15"
// but that might also be a valid nonce in compliance with PoW(H!n, n) < (2^256 / difficulty)
assertEquals(expectedNonce, Hex.toHexString(block.getNonce()));
}
}
@Test
@Ignore
public void testMine2() {
boolean miningTestEnabled = true;
if (miningTestEnabled) {
Block block = createBlock(null);
logger.info("Minning on block: [{}] ", block.getNumber());
// assertEquals(rlpWithoutNonce, Hex.toHexString(block.getEncodedWithoutNonce()));
// System.out.println("Searching for nonce of following block: \n" + block.toString());
Miner miner = new Miner();
boolean mined = miner.mine(block, block.getDifficulty());
assertTrue(mined);
boolean valid = block.validateNonce();
assertTrue(valid);
logger.info("found nonce: [{}]", Hex.toHexString(block.getNonce()));
while (true) {
Block newBlock = createBlock(block);
mined = miner.mine(newBlock, newBlock.getDifficulty());
assertTrue(mined);
valid = newBlock.validateNonce();
assertTrue(valid);
block = newBlock;
logger.info("found nonce: [{}]", Hex.toHexString(newBlock.getNonce()));
logger.info("block.number: [{}], added to the chain", newBlock.getNumber());
}
}
}
/**
* Produces a block equal to block#32 on PoC5 testnet (protocol 19)
* Where nonce was '0000000000000000000000000000000000000000000000001f52ebb192c4ea97'
* and resulting hash 'ce7201f6cc5eb1a6f35c7dda8acda111647a0f8a5bf0518e46579b03e29fe14b'
*/
private Block createBlock(Block lastBlock) {
if (lastBlock == null) {
byte[] parentHash = Hex.decode("0a312c2b0a8f125c60a3976b6e508e740e095eb59943988d9bbfb8aa43922e31");
byte[] unclesHash = Hex.decode("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347");
byte[] coinbase = Hex.decode("e559de5527492bcb42ec68d07df0742a98ec3f1e");
byte[] difficulty = Hex.decode("02eb75");
byte[] nonce = null;
long number = 32;
long minGasPrice = 10000000000000L;
long gasLimit = 969216;
long gasUsed = 0;
long timestamp = 1401421088;
byte[] stateRoot = Hex.decode("50188ab86bdf164ac90eb2835a04a8930aae5393c3a2ef1166fb95028f9456b8");
Block newBlock = new Block(parentHash, unclesHash, coinbase, null,
difficulty, number, gasLimit, gasUsed, timestamp,
null, nonce, null, null);
// Setting stateRoot manually, because don't have state available.
return newBlock;
} else {
Block newBlock = new Block(lastBlock.getHash(), lastBlock.getUnclesHash(), lastBlock.getCoinbase(), null,
lastBlock.getDifficulty(), lastBlock.getNumber() + 1,
lastBlock.getGasLimit(), lastBlock.getGasUsed(), lastBlock.getTimestamp(),
null, null, null, null);
return newBlock;
}
}
}

View File

@ -1,127 +0,0 @@
package test.ethereum.core;
import org.ethereum.core.PremineRaw;
import test.ethereum.db.MockDB;
import org.ethereum.core.AccountState;
import org.ethereum.core.Genesis;
import org.ethereum.crypto.HashUtil;
import org.ethereum.trie.Trie;
import org.ethereum.trie.TrieImpl;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import static org.junit.Assert.assertEquals;
public class StateTest {
private static final String GENESIS_STATE_ROOT = "7e204dc9cfb7acdf062ff0b8052f7fcb0b7e6593754773967932ce458d134af3";
private static final Logger logger = LoggerFactory.getLogger("test");
@Test
public void testGenesisAccounts() {
Trie trie = generateGenesisState();
assertEquals(GENESIS_STATE_ROOT, Hex.toHexString(trie.getRootHash()));
}
@Test // calc state after applying first tx on genesis
public void test2() {
// explanation:
// 0) create genesis
// 1) apply cost of tx to cd2a3d9f938e13cd947ec05abc7fe734df8dd826
// 2) create AccountState for 77045e71a7a2c50903d88e564cd72fab11e82051
// 3) minner gets the gas + coinbase ==> 6260000000000000 + 1500000000000000000
// 4) calc the root
Trie trie = generateGenesisState();
String expected = "c12b4d771fbcc0d56ec106f8d465d24b9d4c36d60275bbafa7d69694d6708660";
// Get and update sender in world state
byte[] cowAddress = Hex.decode("cd2a3d9f938e13cd947ec05abc7fe734df8dd826");
byte[] rlpEncodedState = trie.get(cowAddress);
AccountState account_1 = new AccountState(rlpEncodedState);
account_1.addToBalance(new BigInteger("-6260000000001000"));
account_1.incrementNonce();
trie.update(cowAddress, account_1.getEncoded());
// Add contract to world state
byte[] codeData = Hex.decode("61778e600054");
AccountState account_2 = new AccountState(BigInteger.ZERO, BigInteger.valueOf(1000));
account_2.setCodeHash(HashUtil.sha3(codeData));
byte[] contractAddress = Hex.decode("77045e71a7a2c50903d88e564cd72fab11e82051"); // generated based on sender + nonce
trie.update(contractAddress, account_2.getEncoded());
// this is saved in the db
// trie.update(HashUtil.sha3(codeData), codeData);
// Update miner in world state
byte[] minerAddress = Hex.decode("4c5f4d519dff3c16f0d54b6866e256fbbbc1a600");
AccountState account_3 = new AccountState(BigInteger.ZERO, new BigInteger("1506260000000000000"));
trie.update(minerAddress, account_3.getEncoded());
assertEquals(expected, Hex.toHexString(trie.getRootHash()));
/* *** GROSS DATA ***
BlockData [
hash=22cf863ab836a6f5c29389d2e77f4792a3b3b52908c98ed14b1cbe91491a3e36
parentHash=77ef4fdaf389dca53236bcf7f72698e154eab2828f86fbc4fc6cd9225d285c89
unclesHash=1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347
coinbase=4c5f4d519dff3c16f0d54b6866e256fbbbc1a600
stateHash=69c21ff84a5af0b53b11c61110a16d6ad43dad37b3eb29ae8e88c936eb06456a
txTrieHash=a77691cf47bec9021d3f027fc8ef2d51b758b600a79967154354b8e37108896f
difficulty=3ff000
number=1
minGasPrice=10000000000000
gasLimit=999023
gasUsed=626
timestamp=1401979976 (2014.06.05 15:52:56)
extraData=null
nonce=0000000000000000000000000000000000000000000000005d439960040e4505
TransactionReceipt[
TransactionData [ hash=1ee6fa3149a5e9c09b54009eb6e108aaa7ecd79483d57eedcf2dff93a1505588 nonce=null,
gasPrice=09184e72a000, gas=03e8, receiveAddress=0000000000000000000000000000000000000000, value=03e8,
data=60016000546006601160003960066000f261778e600054, signatureV=27,
signatureR=2b379f22050e3554c3fa5423d9040bb28dcc7f905300db4e67c03bcf9b27003c,
signatureS=59f47793e050974e6b5fca2848b19925637b883a012693b54d712f1c4f74def5
]
, postTxState=7fa5bd00f6e03b5a5718560f1e25179b227167585a3c3da06a48f554365fb527
, cumulativeGas=0272]
]
+++ 4c5f4d519dff3c16f0d54b6866e256fbbbc1a600:
+++ 77045e71a7a2c50903d88e564cd72fab11e82051: $[61,77,8e,60,0,54] ([])
* cd2a3d9f938e13cd947ec05abc7fe734df8dd826: #1 1606938044258990275541962092341162602522202987522792835300376 (-6260000000001000)
*/
assertEquals(expected, Hex.toHexString(trie.getRootHash()));
}
private Trie generateGenesisState() {
Trie trie = new TrieImpl(new MockDB());
for (PremineRaw raw : Genesis.getPremine()) {
AccountState acctState = new AccountState(BigInteger.ZERO,
raw.getValue().multiply(raw.getDenomination().value()));
trie.update(raw.getAddr(), acctState.getEncoded());
}
return trie;
}
}

View File

@ -1,43 +0,0 @@
package test.ethereum.core;
import org.ethereum.core.TransactionReceipt;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import static org.junit.Assert.assertEquals;
/**
* @author Roman Mandeleil
* @since 05.12.2014
*/
public class TransactionReceiptTest {
private static final Logger logger = LoggerFactory.getLogger("test");
@Test // rlp decode
public void test_1() {
byte[] rlp = Hex.decode("f8c4a0966265cc49fa1f10f0445f035258d116563931022a3570a640af5d73a214a8da822b6fb84000000010000000010000000000008000000000000000000000000000000000000000000000000000000000020000000000000014000000000400000000000440f85cf85a94d5ccd26ba09ce1d85148b5081fa3ed77949417bef842a0000000000000000000000000459d3a7595df9eba241365f4676803586d7d199ca0436f696e7300000000000000000000000000000000000000000000000000000080");
TransactionReceipt txReceipt = new TransactionReceipt(rlp);
assertEquals(1, txReceipt.getLogInfoList().size());
assertEquals("966265cc49fa1f10f0445f035258d116563931022a3570a640af5d73a214a8da",
Hex.toHexString(txReceipt.getPostTxState()));
assertEquals("2b6f",
Hex.toHexString(txReceipt.getCumulativeGas()));
assertEquals("00000010000000010000000000008000000000000000000000000000000000000000000000000000000000020000000000000014000000000400000000000440",
Hex.toHexString(txReceipt.getBloomFilter().getData()));
logger.info("{}", txReceipt);
}
}

View File

@ -1,307 +0,0 @@
package test.ethereum.core;
import org.ethereum.core.Bloom;
import org.ethereum.core.Transaction;
import org.ethereum.core.TransactionReceipt;
import org.ethereum.crypto.ECKey;
import org.ethereum.crypto.ECKey.MissingPrivateKeyException;
import org.ethereum.crypto.HashUtil;
import org.ethereum.vm.LogInfo;
import org.junit.Ignore;
import org.junit.Test;
import org.spongycastle.util.BigIntegers;
import org.spongycastle.util.encoders.Hex;
import java.io.IOException;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
@Ignore
public class TransactionTest {
@Test /* sign transaction https://tools.ietf.org/html/rfc6979 */
public void test1() throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException, IOException {
//python taken exact data
String txRLPRawData = "a9e880872386f26fc1000085e8d4a510008203e89413978aee95f38490e9769c39b2773ed763d9cd5f80";
// String txRLPRawData = "f82804881bc16d674ec8000094cd2a3d9f938e13cd947ec05abc7fe734df8dd8268609184e72a0006480";
byte[] cowPrivKey = Hex.decode("c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4");
ECKey key = ECKey.fromPrivate(cowPrivKey);
byte[] data = Hex.decode(txRLPRawData);
// step 1: serialize + RLP encode
// step 2: hash = sha3(step1)
byte[] txHash = HashUtil.sha3(data);
String signature = key.doSign(txHash).toBase64();
System.out.println(signature);
}
@Test /* achieve public key of the sender */
public void test2() throws Exception {
// cat --> 79b08ad8787060333663d19704909ee7b1903e58
// cow --> cd2a3d9f938e13cd947ec05abc7fe734df8dd826
BigInteger value = new BigInteger("1000000000000000000000");
byte[] privKey = HashUtil.sha3("cat".getBytes());
ECKey ecKey = ECKey.fromPrivate(privKey);
byte[] senderPrivKey = HashUtil.sha3("cow".getBytes());
byte[] gasPrice = Hex.decode("09184e72a000");
byte[] gas = Hex.decode("4255");
// Tn (nonce); Tp(pgas); Tg(gaslimi); Tt(value); Tv(value); Ti(sender); Tw; Tr; Ts
Transaction tx = new Transaction(null, gasPrice, gas, ecKey.getAddress(),
value.toByteArray(),
null);
tx.sign(senderPrivKey);
System.out.println("v\t\t\t: " + Hex.toHexString(new byte[]{tx.getSignature().v}));
System.out.println("r\t\t\t: " + Hex.toHexString(BigIntegers.asUnsignedByteArray(tx.getSignature().r)));
System.out.println("s\t\t\t: " + Hex.toHexString(BigIntegers.asUnsignedByteArray(tx.getSignature().s)));
System.out.println("RLP encoded tx\t\t: " + Hex.toHexString(tx.getEncoded()));
// retrieve the signer/sender of the transaction
ECKey key = ECKey.signatureToKey(tx.getHash(), tx.getSignature().toBase64());
System.out.println("Tx unsigned RLP\t\t: " + Hex.toHexString(tx.getEncodedRaw()));
System.out.println("Tx signed RLP\t\t: " + Hex.toHexString(tx.getEncoded()));
System.out.println("Signature public key\t: " + Hex.toHexString(key.getPubKey()));
System.out.println("Sender is\t\t: " + Hex.toHexString(key.getAddress()));
assertEquals("cd2a3d9f938e13cd947ec05abc7fe734df8dd826",
Hex.toHexString(key.getAddress()));
System.out.println(tx.toString());
}
@Test /* achieve public key of the sender nonce: 01 */
public void test3() throws Exception {
// cat --> 79b08ad8787060333663d19704909ee7b1903e58
// cow --> cd2a3d9f938e13cd947ec05abc7fe734df8dd826
ECKey ecKey = ECKey.fromPrivate(HashUtil.sha3("cat".getBytes()));
byte[] senderPrivKey = HashUtil.sha3("cow".getBytes());
byte[] nonce = {0x01};
byte[] gasPrice = Hex.decode("09184e72a000");
byte[] gasLimit = Hex.decode("4255");
BigInteger value = new BigInteger("1000000000000000000000000");
Transaction tx = new Transaction(nonce, gasPrice, gasLimit,
ecKey.getAddress(), value.toByteArray(), null);
tx.sign(senderPrivKey);
System.out.println("v\t\t\t: " + Hex.toHexString(new byte[]{tx.getSignature().v}));
System.out.println("r\t\t\t: " + Hex.toHexString(BigIntegers.asUnsignedByteArray(tx.getSignature().r)));
System.out.println("s\t\t\t: " + Hex.toHexString(BigIntegers.asUnsignedByteArray(tx.getSignature().s)));
System.out.println("RLP encoded tx\t\t: " + Hex.toHexString(tx.getEncoded()));
// retrieve the signer/sender of the transaction
ECKey key = ECKey.signatureToKey(tx.getHash(), tx.getSignature().toBase64());
System.out.println("Tx unsigned RLP\t\t: " + Hex.toHexString(tx.getEncodedRaw()));
System.out.println("Tx signed RLP\t\t: " + Hex.toHexString(tx.getEncoded()));
System.out.println("Signature public key\t: " + Hex.toHexString(key.getPubKey()));
System.out.println("Sender is\t\t: " + Hex.toHexString(key.getAddress()));
assertEquals("cd2a3d9f938e13cd947ec05abc7fe734df8dd826",
Hex.toHexString(key.getAddress()));
}
// Testdata from: https://github.com/ethereum/tests/blob/master/txtest.json
String RLP_ENCODED_RAW_TX = "e88085e8d4a510008227109413978aee95f38490e9769c39b2773ed763d9cd5f872386f26fc1000080";
String RLP_ENCODED_UNSIGNED_TX = "eb8085e8d4a510008227109413978aee95f38490e9769c39b2773ed763d9cd5f872386f26fc1000080808080";
String HASH_TX = "328ea6d24659dec48adea1aced9a136e5ebdf40258db30d1b1d97ed2b74be34e";
String RLP_ENCODED_SIGNED_TX = "f86b8085e8d4a510008227109413978aee95f38490e9769c39b2773ed763d9cd5f872386f26fc10000801ba0eab47c1a49bf2fe5d40e01d313900e19ca485867d462fe06e139e3a536c6d4f4a014a569d327dcda4b29f74f93c0e9729d2f49ad726e703f9cd90dbb0fbf6649f1";
String KEY = "c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4";
byte[] testNonce = Hex.decode("");
byte[] testGasPrice = BigIntegers.asUnsignedByteArray(BigInteger.valueOf(1000000000000L));
byte[] testGasLimit = BigIntegers.asUnsignedByteArray(BigInteger.valueOf(10000));
byte[] testReceiveAddress = Hex.decode("13978aee95f38490e9769c39b2773ed763d9cd5f");
byte[] testValue = BigIntegers.asUnsignedByteArray(BigInteger.valueOf(10000000000000000L));
byte[] testData = Hex.decode("");
byte[] testInit = Hex.decode("");
@Test
public void testTransactionFromSignedRLP() throws Exception {
Transaction txSigned = new Transaction(Hex.decode(RLP_ENCODED_SIGNED_TX));
assertEquals(HASH_TX, Hex.toHexString(txSigned.getHash()));
assertEquals(RLP_ENCODED_SIGNED_TX, Hex.toHexString(txSigned.getEncoded()));
assertEquals(BigInteger.ZERO, new BigInteger(1, txSigned.getNonce()));
assertEquals(new BigInteger(1, testGasPrice), new BigInteger(1, txSigned.getGasPrice()));
assertEquals(new BigInteger(1, testGasLimit), new BigInteger(1, txSigned.getGasLimit()));
assertEquals(Hex.toHexString(testReceiveAddress), Hex.toHexString(txSigned.getReceiveAddress()));
assertEquals(new BigInteger(1, testValue), new BigInteger(1, txSigned.getValue()));
assertNull(txSigned.getData());
assertEquals(27, txSigned.getSignature().v);
assertEquals("eab47c1a49bf2fe5d40e01d313900e19ca485867d462fe06e139e3a536c6d4f4", Hex.toHexString(BigIntegers.asUnsignedByteArray(txSigned.getSignature().r)));
assertEquals("14a569d327dcda4b29f74f93c0e9729d2f49ad726e703f9cd90dbb0fbf6649f1", Hex.toHexString(BigIntegers.asUnsignedByteArray(txSigned.getSignature().s)));
}
@Test
public void testTransactionFromUnsignedRLP() throws Exception {
Transaction txUnsigned = new Transaction(Hex.decode(RLP_ENCODED_UNSIGNED_TX));
assertEquals(HASH_TX, Hex.toHexString(txUnsigned.getHash()));
assertEquals(RLP_ENCODED_UNSIGNED_TX, Hex.toHexString(txUnsigned.getEncoded()));
txUnsigned.sign(Hex.decode(KEY));
assertEquals(RLP_ENCODED_SIGNED_TX, Hex.toHexString(txUnsigned.getEncoded()));
assertEquals(BigInteger.ZERO, new BigInteger(1, txUnsigned.getNonce()));
assertEquals(new BigInteger(1, testGasPrice), new BigInteger(1, txUnsigned.getGasPrice()));
assertEquals(new BigInteger(1, testGasLimit), new BigInteger(1, txUnsigned.getGasLimit()));
assertEquals(Hex.toHexString(testReceiveAddress), Hex.toHexString(txUnsigned.getReceiveAddress()));
assertEquals(new BigInteger(1, testValue), new BigInteger(1, txUnsigned.getValue()));
assertNull(txUnsigned.getData());
assertEquals(27, txUnsigned.getSignature().v);
assertEquals("eab47c1a49bf2fe5d40e01d313900e19ca485867d462fe06e139e3a536c6d4f4", Hex.toHexString(BigIntegers.asUnsignedByteArray(txUnsigned.getSignature().r)));
assertEquals("14a569d327dcda4b29f74f93c0e9729d2f49ad726e703f9cd90dbb0fbf6649f1", Hex.toHexString(BigIntegers.asUnsignedByteArray(txUnsigned.getSignature().s)));
}
@Test
public void testTransactionFromNew1() throws MissingPrivateKeyException {
Transaction txNew = new Transaction(testNonce, testGasPrice, testGasLimit, testReceiveAddress, testValue, testData);
assertEquals("", Hex.toHexString(txNew.getNonce()));
assertEquals(new BigInteger(1, testGasPrice), new BigInteger(1, txNew.getGasPrice()));
assertEquals(new BigInteger(1, testGasLimit), new BigInteger(1, txNew.getGasLimit()));
assertEquals(Hex.toHexString(testReceiveAddress), Hex.toHexString(txNew.getReceiveAddress()));
assertEquals(new BigInteger(1, testValue), new BigInteger(1, txNew.getValue()));
assertEquals("", Hex.toHexString(txNew.getData()));
assertNull(txNew.getSignature());
assertEquals(RLP_ENCODED_RAW_TX, Hex.toHexString(txNew.getEncodedRaw()));
assertEquals(HASH_TX, Hex.toHexString(txNew.getHash()));
assertEquals(RLP_ENCODED_UNSIGNED_TX, Hex.toHexString(txNew.getEncoded()));
txNew.sign(Hex.decode(KEY));
assertEquals(RLP_ENCODED_SIGNED_TX, Hex.toHexString(txNew.getEncoded()));
assertEquals(27, txNew.getSignature().v);
assertEquals("eab47c1a49bf2fe5d40e01d313900e19ca485867d462fe06e139e3a536c6d4f4", Hex.toHexString(BigIntegers.asUnsignedByteArray(txNew.getSignature().r)));
assertEquals("14a569d327dcda4b29f74f93c0e9729d2f49ad726e703f9cd90dbb0fbf6649f1", Hex.toHexString(BigIntegers.asUnsignedByteArray(txNew.getSignature().s)));
}
@Test
public void testTransactionFromNew2() throws MissingPrivateKeyException {
byte[] privKeyBytes = Hex.decode("c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4");
String RLP_TX_UNSIGNED = "eb8085e8d4a510008227109413978aee95f38490e9769c39b2773ed763d9cd5f872386f26fc1000080808080";
String RLP_TX_SIGNED = "f86b8085e8d4a510008227109413978aee95f38490e9769c39b2773ed763d9cd5f872386f26fc10000801ba0eab47c1a49bf2fe5d40e01d313900e19ca485867d462fe06e139e3a536c6d4f4a014a569d327dcda4b29f74f93c0e9729d2f49ad726e703f9cd90dbb0fbf6649f1";
String HASH_TX_UNSIGNED = "328ea6d24659dec48adea1aced9a136e5ebdf40258db30d1b1d97ed2b74be34e";
byte[] nonce = BigIntegers.asUnsignedByteArray(BigInteger.ZERO);
byte[] gasPrice = Hex.decode("e8d4a51000"); // 1000000000000
byte[] gas = Hex.decode("2710"); // 10000
byte[] recieveAddress = Hex.decode("13978aee95f38490e9769c39b2773ed763d9cd5f");
byte[] value = Hex.decode("2386f26fc10000"); //10000000000000000"
byte[] data = new byte[0];
Transaction tx = new Transaction(nonce, gasPrice, gas, recieveAddress, value, data);
// Testing unsigned
String encodedUnsigned = Hex.toHexString(tx.getEncoded());
assertEquals(RLP_TX_UNSIGNED, encodedUnsigned);
assertEquals(HASH_TX_UNSIGNED, Hex.toHexString(tx.getHash()));
// Testing signed
tx.sign(privKeyBytes);
String encodedSigned = Hex.toHexString(tx.getEncoded());
assertEquals(RLP_TX_SIGNED, encodedSigned);
assertEquals(HASH_TX_UNSIGNED, Hex.toHexString(tx.getHash()));
}
@Test
public void testTransactionCreateContract() {
// String rlp =
// "f89f808609184e72a0008203e8808203e8b84b4560005444602054600f60056002600a02010b0d630000001d596002602054630000003b5860066000530860056006600202010a0d6300000036596004604054630000003b5860056060541ca0ddc901d83110ea50bc40803f42083afea1bbd420548f6392a679af8e24b21345a06620b3b512bea5f0a272703e8d6933177c23afc79516fd0ca4a204aa6e34c7e9";
byte[] senderPrivKey = HashUtil.sha3("cow".getBytes());
byte[] nonce = BigIntegers.asUnsignedByteArray(BigInteger.ZERO);
byte[] gasPrice = Hex.decode("09184e72a000"); // 10000000000000
byte[] gas = Hex.decode("03e8"); // 1000
byte[] recieveAddress = null;
byte[] endowment = Hex.decode("03e8"); //10000000000000000"
byte[] init = Hex.decode
("4560005444602054600f60056002600a02010b0d630000001d596002602054630000003b5860066000530860056006600202010a0d6300000036596004604054630000003b586005606054");
Transaction tx1 = new Transaction(nonce, gasPrice, gas,
recieveAddress, endowment, init);
tx1.sign(senderPrivKey);
byte[] payload = tx1.getEncoded();
System.out.println(Hex.toHexString(payload));
Transaction tx2 = new Transaction(payload);
// tx2.getSender();
String plainTx1 = Hex.toHexString(tx1.getEncodedRaw());
String plainTx2 = Hex.toHexString(tx2.getEncodedRaw());
// Transaction tx = new Transaction(Hex.decode(rlp));
System.out.println("tx1.hash: " + Hex.toHexString(tx1.getHash()));
System.out.println("tx2.hash: " + Hex.toHexString(tx2.getHash()));
System.out.println();
System.out.println("plainTx1: " + plainTx1);
System.out.println("plainTx2: " + plainTx2);
System.out.println(Hex.toHexString(tx2.getSender()));
}
@Test
public void encodeReceiptTest() {
String data = "f90244a0f5ff3fbd159773816a7c707a9b8cb6bb778b934a8f6466c7830ed970498f4b688301e848b902000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dbda94cd2a3d9f938e13cd947ec05abc7fe734df8dd826c083a1a1a1";
byte[] stateRoot = Hex.decode("f5ff3fbd159773816a7c707a9b8cb6bb778b934a8f6466c7830ed970498f4b68");
byte[] gasUsed = Hex.decode("01E848");
Bloom bloom = new Bloom(Hex.decode("0000000000000000800000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"));
LogInfo logInfo1 = new LogInfo(
Hex.decode("cd2a3d9f938e13cd947ec05abc7fe734df8dd826"),
null,
Hex.decode("a1a1a1")
);
List<LogInfo> logs = new ArrayList<>();
logs.add(logInfo1);
TransactionReceipt receipt = new TransactionReceipt(stateRoot, gasUsed, bloom, logs);
assertEquals(data,
Hex.toHexString(receipt.getEncoded()));
}
}

View File

@ -1,151 +0,0 @@
package test.ethereum.core;
import test.ethereum.TestContext;
import org.ethereum.config.SystemProperties;
import org.ethereum.core.Transaction;
import org.ethereum.core.Wallet;
import org.ethereum.crypto.ECKey;
import org.ethereum.crypto.HashUtil;
import org.ethereum.facade.Repository;
import org.ethereum.manager.WorldManager;
import org.junit.After;
import org.junit.Assert;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import org.xml.sax.SAXException;
import java.io.IOException;
import java.math.BigInteger;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
/**
* @author Roman Mandeleil
* @since 17.05.14
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class WalletTest {
private static final Logger logger = LoggerFactory.getLogger("test");
@Configuration
@ComponentScan(basePackages = "org.ethereum")
static class ContextConfiguration extends TestContext {
static {
SystemProperties.CONFIG.setDataBaseDir("test_db/" + WalletTest.class);
}
}
@Autowired
WorldManager worldManager;
@After
public void doReset() {
worldManager.reset();
}
@Ignore
@Test // Testing account for simple balance set
public void accountTest_1() {
Repository repository = worldManager.getRepository();
ECKey cowKey = ECKey.fromPrivate(HashUtil.sha3("cow".getBytes()));
repository.createAccount(cowKey.getAddress());
repository.addBalance(cowKey.getAddress(), BigInteger.TEN);
Wallet wallet = new Wallet();
wallet.setWorldManager(worldManager);
wallet.importKey(cowKey.getPrivKeyBytes());
BigInteger walletBalance = wallet.getBalance(cowKey.getAddress());
Assert.assertEquals(BigInteger.TEN, walletBalance);
}
@Ignore
@Test // test account balance with pending "unblocked" transaction
public void accountTest_2() {
Repository repository = worldManager.getRepository();
ECKey cowKey = ECKey.fromPrivate(HashUtil.sha3("cow".getBytes()));
repository.createAccount(cowKey.getAddress());
repository.addBalance(cowKey.getAddress(), BigInteger.TEN);
Wallet wallet = new Wallet();
wallet.setWorldManager(worldManager);
wallet.importKey(cowKey.getPrivKeyBytes());
Transaction tx = new Transaction(
new byte[]{},
Hex.decode("09184E72A000"),
Hex.decode("03E8"),
cowKey.getAddress(),
Hex.decode("0A"),
new byte[]{}
);
ECKey catKey = ECKey.fromPrivate(HashUtil.sha3("cat".getBytes()));
tx.sign(catKey.getPrivKeyBytes());
wallet.applyTransaction(tx);
BigInteger walletBalance = wallet.getBalance(cowKey.getAddress());
Assert.assertEquals(BigInteger.valueOf(20), walletBalance);
}
@Ignore
@Test
public void testSave1() throws TransformerException, ParserConfigurationException {
Wallet wallet = new Wallet();
wallet.setWorldManager(worldManager);
ECKey cowKey = ECKey.fromPrivate(HashUtil.sha3("cow".getBytes()));
ECKey catKey = ECKey.fromPrivate(HashUtil.sha3("cat".getBytes()));
wallet.importKey(cowKey.getPrivKeyBytes());
wallet.importKey(catKey.getPrivKeyBytes());
wallet.setHigh(4354);
wallet.save();
}
@Test
@Ignore
public void testLoad1() throws TransformerException,
ParserConfigurationException, IOException, SAXException {
Wallet wallet = new Wallet();
wallet.load();
}
}

View File

@ -1,105 +0,0 @@
package test.ethereum.crypto;
import org.ethereum.crypto.ECKey;
import org.ethereum.crypto.HashUtil;
import org.ethereum.util.Utils;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import static org.junit.Assert.assertEquals;
public class CryptoTest {
@Test
public void test1() {
byte[] result = HashUtil.sha3("horse".getBytes());
assertEquals("c87f65ff3f271bf5dc8643484f66b200109caffe4bf98c4cb393dc35740b28c0",
Hex.toHexString(result));
result = HashUtil.sha3("cow".getBytes());
assertEquals("c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4",
Hex.toHexString(result));
}
@Test
public void test3() {
BigInteger privKey = new BigInteger("cd244b3015703ddf545595da06ada5516628c5feadbf49dc66049c4b370cc5d8", 16);
byte[] addr = ECKey.fromPrivate(privKey).getAddress();
assertEquals("89b44e4d3c81ede05d0f5de8d1a68f754d73d997", Hex.toHexString(addr));
}
@Test
public void test4() {
byte[] cowBytes = HashUtil.sha3("cow".getBytes());
byte[] addr = ECKey.fromPrivate(cowBytes).getAddress();
assertEquals("CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826", Hex.toHexString(addr).toUpperCase());
}
@Test
public void test5() {
byte[] horseBytes = HashUtil.sha3("horse".getBytes());
byte[] addr = ECKey.fromPrivate(horseBytes).getAddress();
assertEquals("13978AEE95F38490E9769C39B2773ED763D9CD5F", Hex.toHexString(addr).toUpperCase());
}
@Test /* performance test */
public void test6() {
long firstTime = System.currentTimeMillis();
System.out.println(firstTime);
for (int i = 0; i < 1000; ++i) {
byte[] horseBytes = HashUtil.sha3("horse".getBytes());
byte[] addr = ECKey.fromPrivate(horseBytes).getAddress();
assertEquals("13978AEE95F38490E9769C39B2773ED763D9CD5F", Hex.toHexString(addr).toUpperCase());
}
long secondTime = System.currentTimeMillis();
System.out.println(secondTime);
System.out.println(secondTime - firstTime + " millisec");
// 1) result: ~52 address calculation every second
}
@Test /* real tx hash calc */
public void test7() {
String txRaw = "F89D80809400000000000000000000000000000000000000008609184E72A000822710B3606956330C0D630000003359366000530A0D630000003359602060005301356000533557604060005301600054630000000C5884336069571CA07F6EB94576346488C6253197BDE6A7E59DDC36F2773672C849402AA9C402C3C4A06D254E662BF7450DD8D835160CBB053463FED0B53F2CDD7F3EA8731919C8E8CC";
byte[] txHashB = HashUtil.sha3(Hex.decode(txRaw));
String txHash = Hex.toHexString(txHashB);
assertEquals("4b7d9670a92bf120d5b43400543b69304a14d767cf836a7f6abff4edde092895", txHash);
}
@Test /* real block hash calc */
public void test8() {
String blockRaw = "F885F8818080A01DCC4DE8DEC75D7AAB85B567B6CCD41AD312451B948A7413F0A142FD40D49347940000000000000000000000000000000000000000A0BCDDD284BF396739C224DBA0411566C891C32115FEB998A3E2B4E61F3F35582AA01DCC4DE8DEC75D7AAB85B567B6CCD41AD312451B948A7413F0A142FD40D4934783800000808080C0C0";
byte[] blockHashB = HashUtil.sha3(Hex.decode(blockRaw));
String blockHash = Hex.toHexString(blockHashB);
System.out.println(blockHash);
}
@Test
public void test9() {
// TODO: https://tools.ietf.org/html/rfc6979#section-2.2
// TODO: https://github.com/bcgit/bc-java/blob/master/core/src/main/java/org/bouncycastle/crypto/signers/ECDSASigner.java
System.out.println(new BigInteger(Hex.decode("3913517ebd3c0c65000000")));
System.out.println(Utils.getValueShortString(new BigInteger("69000000000000000000000000")));
}
@Test
public void test10() {
BigInteger privKey = new BigInteger("74ef8a796480dda87b4bc550b94c408ad386af0f65926a392136286784d63858", 16);
byte[] addr = ECKey.fromPrivate(privKey).getAddress();
assertEquals("ba73facb4f8291f09f27f90fe1213537b910065e", Hex.toHexString(addr));
}
}

View File

@ -1,55 +0,0 @@
package test.ethereum.crypto;
import org.ethereum.crypto.ECIESCoder;
import org.ethereum.crypto.ECKey;
import org.junit.Assert;
import org.junit.Test;
import org.spongycastle.math.ec.ECPoint;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
public class ECIESCoderTest {
@Test // decrypt cpp data
public void test1(){
BigInteger privKey = new BigInteger("5e173f6ac3c669587538e7727cf19b782a4f2fda07c1eaa662c593e5e85e3051", 16);
byte[] cipher = Hex.decode("049934a7b2d7f9af8fd9db941d9da281ac9381b5740e1f64f7092f3588d4f87f5ce55191a6653e5e80c1c5dd538169aa123e70dc6ffc5af1827e546c0e958e42dad355bcc1fcb9cdf2cf47ff524d2ad98cbf275e661bf4cf00960e74b5956b799771334f426df007350b46049adb21a6e78ab1408d5e6ccde6fb5e69f0f4c92bb9c725c02f99fa72b9cdc8dd53cff089e0e73317f61cc5abf6152513cb7d833f09d2851603919bf0fbe44d79a09245c6e8338eb502083dc84b846f2fee1cc310d2cc8b1b9334728f97220bb799376233e113");
byte[] payload = new byte[0];
try {
payload = ECIESCoder.decrypt(privKey, cipher);
} catch (Throwable e) {e.printStackTrace();}
Assert.assertEquals("802b052f8b066640bba94a4fc39d63815c377fced6fcb84d27f791c9921ddf3e9bf0108e298f490812847109cbd778fae393e80323fd643209841a3b7f110397f37ec61d84cea03dcc5e8385db93248584e8af4b4d1c832d8c7453c0089687a700",
Hex.toHexString(payload));
}
@Test // encrypt decrypt round trip
public void test2(){
BigInteger privKey = new BigInteger("5e173f6ac3c669587538e7727cf19b782a4f2fda07c1eaa662c593e5e85e3051", 16);
byte[] payload = Hex.decode("1122334455");
ECKey ecKey = ECKey.fromPrivate(privKey);
ECPoint pubKeyPoint = ecKey.getPubKeyPoint();
byte[] cipher = new byte[0];
try {
cipher = ECIESCoder.encrypt(pubKeyPoint, payload);
} catch (Throwable e) {e.printStackTrace();}
System.out.println(Hex.toHexString(cipher));
byte[] decrypted_payload = new byte[0];
try {
decrypted_payload = ECIESCoder.decrypt(privKey, cipher);
} catch (Throwable e) {e.printStackTrace();}
System.out.println(Hex.toHexString(decrypted_payload));
}
}

View File

@ -1,146 +0,0 @@
package test.ethereum.crypto;
import org.ethereum.ConcatKDFBytesGenerator;
import org.ethereum.crypto.ECKey;
import org.ethereum.crypto.EthereumIESEngine;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.asn1.sec.SECNamedCurves;
import org.spongycastle.asn1.x9.X9ECParameters;
import org.spongycastle.crypto.*;
import org.spongycastle.crypto.agreement.ECDHBasicAgreement;
import org.spongycastle.crypto.digests.SHA256Digest;
import org.spongycastle.crypto.engines.AESFastEngine;
import org.spongycastle.crypto.generators.ECKeyPairGenerator;
import org.spongycastle.crypto.macs.HMac;
import org.spongycastle.crypto.modes.SICBlockCipher;
import org.spongycastle.crypto.params.*;
import org.spongycastle.math.ec.ECPoint;
import org.spongycastle.util.encoders.Hex;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.security.Security;
import static org.junit.Assert.assertArrayEquals;
public class ECIESTest {
public static final int KEY_SIZE = 128;
static Logger log = LoggerFactory.getLogger("test");
private static ECDomainParameters curve;
private static final String CIPHERTEXT1 = "042a851331790adacf6e64fcb19d0872fcdf1285a899a12cdc897da941816b0ea6485402aaf6c2e0a5d98ae3af1b05c68b307d1e0eb7a426a46f1617ba5b94f90b606eee3b5e9d2b527a9ee52cfa377bcd118b9390ed27ffe7d48e8155004375cae209012c3e057bb13a478a64a201d79ad4ae83";
private static final X9ECParameters IES_CURVE_PARAM = SECNamedCurves.getByName("secp256r1");
private static final BigInteger PRIVATE_KEY1 = new BigInteger("51134539186617376248226283012294527978458758538121566045626095875284492680246");
private static ECPoint pub(BigInteger d) {
return curve.getG().multiply(d);
}
@BeforeClass
public static void beforeAll() {
if (Security.getProvider("SC") == null)
Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1);
curve = new ECDomainParameters(IES_CURVE_PARAM.getCurve(), IES_CURVE_PARAM.getG(), IES_CURVE_PARAM.getN(), IES_CURVE_PARAM.getH());
}
@Test
public void testKDF() {
ConcatKDFBytesGenerator kdf = new ConcatKDFBytesGenerator(new SHA256Digest());
kdf.init(new KDFParameters("Hello".getBytes(), new byte[0]));
byte[] bytes = new byte[2];
kdf.generateBytes(bytes, 0, bytes.length);
assertArrayEquals(new byte[]{-66, -89}, bytes);
}
@Test
public void testDecryptTestVector() throws IOException, InvalidCipherTextException {
ECPoint pub1 = pub(PRIVATE_KEY1);
byte[] ciphertext = Hex.decode(CIPHERTEXT1);
byte[] plaintext = decrypt(PRIVATE_KEY1, ciphertext);
assertArrayEquals(new byte[]{1,1,1}, plaintext);
}
@Test
public void testRoundTrip() throws InvalidCipherTextException, IOException {
ECPoint pub1 = pub(PRIVATE_KEY1);
byte[] plaintext = "Hello world".getBytes();
byte[] ciphertext = encrypt(pub1, plaintext);
byte[] plaintext1 = decrypt(PRIVATE_KEY1, ciphertext);
assertArrayEquals(plaintext, plaintext1);
}
public static byte[] decrypt(BigInteger prv, byte[] cipher) throws InvalidCipherTextException, IOException {
ByteArrayInputStream is = new ByteArrayInputStream(cipher);
byte[] ephemBytes = new byte[2*((curve.getCurve().getFieldSize()+7)/8) + 1];
is.read(ephemBytes);
ECPoint ephem = curve.getCurve().decodePoint(ephemBytes);
byte[] IV = new byte[KEY_SIZE /8];
is.read(IV);
byte[] cipherBody = new byte[is.available()];
is.read(cipherBody);
EthereumIESEngine iesEngine = makeIESEngine(false, ephem, prv, IV);
byte[] message = iesEngine.processBlock(cipherBody, 0, cipherBody.length);
return message;
}
public static byte[] encrypt(ECPoint toPub, byte[] plaintext) throws InvalidCipherTextException, IOException {
ECKeyPairGenerator eGen = new ECKeyPairGenerator();
SecureRandom random = new SecureRandom();
KeyGenerationParameters gParam = new ECKeyGenerationParameters(curve, random);
eGen.init(gParam);
byte[] IV = new byte[KEY_SIZE/8];
new SecureRandom().nextBytes(IV);
AsymmetricCipherKeyPair ephemPair = eGen.generateKeyPair();
BigInteger prv = ((ECPrivateKeyParameters)ephemPair.getPrivate()).getD();
ECPoint pub = ((ECPublicKeyParameters)ephemPair.getPublic()).getQ();
EthereumIESEngine iesEngine = makeIESEngine(true, toPub, prv, IV);
ECKeyGenerationParameters keygenParams = new ECKeyGenerationParameters(curve, random);
ECKeyPairGenerator generator = new ECKeyPairGenerator();
generator.init(keygenParams);
ECKeyPairGenerator gen = new ECKeyPairGenerator();
gen.init(new ECKeyGenerationParameters(ECKey.CURVE, random));
byte[] cipher = iesEngine.processBlock(plaintext, 0, plaintext.length);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bos.write(pub.getEncoded(false));
bos.write(IV);
bos.write(cipher);
return bos.toByteArray();
}
private static EthereumIESEngine makeIESEngine(boolean isEncrypt, ECPoint pub, BigInteger prv, byte[] IV) {
AESFastEngine aesFastEngine = new AESFastEngine();
EthereumIESEngine iesEngine = new EthereumIESEngine(
new ECDHBasicAgreement(),
new ConcatKDFBytesGenerator(new SHA256Digest()),
new HMac(new SHA256Digest()),
new SHA256Digest(),
new BufferedBlockCipher(new SICBlockCipher(aesFastEngine)));
byte[] d = new byte[] {};
byte[] e = new byte[] {};
IESParameters p = new IESWithCipherParameters(d, e, KEY_SIZE, KEY_SIZE);
ParametersWithIV parametersWithIV = new ParametersWithIV(p, IV);
iesEngine.init(isEncrypt, new ECPrivateKeyParameters(prv, curve), new ECPublicKeyParameters(pub, curve), parametersWithIV);
return iesEngine;
}
}

View File

@ -1,291 +0,0 @@
package test.ethereum.crypto;
import org.ethereum.core.Transaction;
import org.ethereum.crypto.ECKey;
import org.ethereum.crypto.ECKey.ECDSASignature;
import org.ethereum.crypto.HashUtil;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import java.io.IOException;
import java.math.BigInteger;
import java.security.SignatureException;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.junit.Assert.*;
public class ECKeyTest {
private static final Logger log = LoggerFactory.getLogger(ECKeyTest.class);
private String privString = "3ecb44df2159c26e0f995712d4f39b6f6e499b40749b1cf1246c37f9516cb6a4";
private BigInteger privateKey = new BigInteger(Hex.decode(privString));
private String pubString = "0497466f2b32bc3bb76d4741ae51cd1d8578b48d3f1e68da206d47321aec267ce78549b514e4453d74ef11b0cd5e4e4c364effddac8b51bcfc8de80682f952896f";
private String compressedPubString = "0397466f2b32bc3bb76d4741ae51cd1d8578b48d3f1e68da206d47321aec267ce7";
private byte[] pubKey = Hex.decode(pubString);
private byte[] compressedPubKey = Hex.decode(compressedPubString);
private String address = "8a40bfaa73256b60764c1bf40675a99083efb075";
private String exampleMessage = new String("This is an example of a signed message.");
private String sigBase64 = "HD5AsBr4wuH6UU9tXuSJhUvgfGayfwoY0cKT03sFUjnpQsupHznd/3mCIRfLuNHlRCVGdAyHecdyM8IVZMtc1I8=";
@Test
public void testHashCode() {
Assert.assertEquals(1866897155, ECKey.fromPrivate(privateKey).hashCode());
}
@Test
public void testECKey() {
ECKey key = new ECKey();
assertTrue(key.isPubKeyCanonical());
assertNotNull(key.getPubKey());
assertNotNull(key.getPrivKeyBytes());
log.debug(Hex.toHexString(key.getPrivKeyBytes()) + " :Generated privkey");
log.debug(Hex.toHexString(key.getPubKey()) + " :Generated pubkey");
}
@Test
public void testFromPrivateKey() {
ECKey key = ECKey.fromPrivate(privateKey).decompress();
assertTrue(key.isPubKeyCanonical());
assertTrue(key.hasPrivKey());
assertArrayEquals(pubKey, key.getPubKey());
}
@Test(expected = IllegalArgumentException.class)
public void testPrivatePublicKeyBytesNoArg() {
new ECKey(null, null);
fail("Expecting an IllegalArgumentException for using only null-parameters");
}
@Test
public void testIsPubKeyOnly() {
ECKey key = ECKey.fromPublicOnly(pubKey);
assertTrue(key.isPubKeyCanonical());
assertTrue(key.isPubKeyOnly());
assertArrayEquals(key.getPubKey(), pubKey);
}
@Test
public void testPublicKeyFromPrivate() {
byte[] pubFromPriv = ECKey.publicKeyFromPrivate(privateKey, false);
assertArrayEquals(pubKey, pubFromPriv);
}
@Test
public void testPublicKeyFromPrivateCompressed() {
byte[] pubFromPriv = ECKey.publicKeyFromPrivate(privateKey, true);
assertArrayEquals(compressedPubKey, pubFromPriv);
}
@Test
public void testGetAddress() {
ECKey key = ECKey.fromPublicOnly(pubKey);
assertArrayEquals(Hex.decode(address), key.getAddress());
}
@Test
public void testToString() {
ECKey key = ECKey.fromPrivate(BigInteger.TEN); // An example private key.
assertEquals("pub:04a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7", key.toString());
}
@Test
public void testEthereumSign() throws IOException {
// TODO: Understand why key must be decompressed for this to work
ECKey key = ECKey.fromPrivate(privateKey).decompress();
System.out.println("Secret\t: " + Hex.toHexString(key.getPrivKeyBytes()));
System.out.println("Pubkey\t: " + Hex.toHexString(key.getPubKey()));
System.out.println("Data\t: " + exampleMessage);
byte[] messageHash = HashUtil.sha3(exampleMessage.getBytes());
ECDSASignature signature = key.sign(messageHash);
String output = signature.toBase64();
System.out.println("Signtr\t: " + output + " (Base64, length: " + output.length() + ")");
assertEquals(sigBase64, output);
}
@Test
public void testVerifySignature1() {
ECKey key = ECKey.fromPublicOnly(pubKey);
BigInteger r = new BigInteger("28157690258821599598544026901946453245423343069728565040002908283498585537001");
BigInteger s = new BigInteger("30212485197630673222315826773656074299979444367665131281281249560925428307087");
ECDSASignature sig = ECDSASignature.fromComponents(r.toByteArray(), s.toByteArray(), (byte) 28);
key.verify(HashUtil.sha3(exampleMessage.getBytes()), sig);
}
@Test
public void testVerifySignature2() {
BigInteger r = new BigInteger("c52c114d4f5a3ba904a9b3036e5e118fe0dbb987fe3955da20f2cd8f6c21ab9c", 16);
BigInteger s = new BigInteger("6ba4c2874299a55ad947dbc98a25ee895aabf6b625c26c435e84bfd70edf2f69", 16);
ECDSASignature sig = ECDSASignature.fromComponents(r.toByteArray(), s.toByteArray(), (byte) 0x1b);
byte[] rawtx = Hex.decode("f82804881bc16d674ec8000094cd2a3d9f938e13cd947ec05abc7fe734df8dd8268609184e72a0006480");
try {
ECKey key = ECKey.signatureToKey(HashUtil.sha3(rawtx), sig.toBase64());
System.out.println("Signature public key\t: " + Hex.toHexString(key.getPubKey()));
System.out.println("Sender is\t\t: " + Hex.toHexString(key.getAddress()));
assertEquals("cd2a3d9f938e13cd947ec05abc7fe734df8dd826", Hex.toHexString(key.getAddress()));
key.verify(HashUtil.sha3(rawtx), sig);
} catch (SignatureException e) {
fail();
}
}
@Test
public void testVerifySignature3() throws SignatureException {
byte[] rawtx = Hex.decode("f86e80893635c9adc5dea000008609184e72a00082109f9479b08ad8787060333663d19704909ee7b1903e58801ba0899b92d0c76cbf18df24394996beef19c050baa9823b4a9828cd9b260c97112ea0c9e62eb4cf0a9d95ca35c8830afac567619d6b3ebee841a3c8be61d35acd8049");
Transaction tx = new Transaction(rawtx);
ECKey key = ECKey.signatureToKey(HashUtil.sha3(rawtx), tx.getSignature().toBase64());
System.out.println("Signature public key\t: " + Hex.toHexString(key.getPubKey()));
System.out.println("Sender is\t\t: " + Hex.toHexString(key.getAddress()));
// sender: CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826
// todo: add test assertion when the sign/verify part actually works.
}
@Test
public void testSValue() throws Exception {
// Check that we never generate an S value that is larger than half the curve order. This avoids a malleability
// issue that can allow someone to change a transaction [hash] without invalidating the signature.
final int ITERATIONS = 10;
ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(ITERATIONS));
List<ListenableFuture<ECKey.ECDSASignature>> sigFutures = Lists.newArrayList();
final ECKey key = new ECKey();
for (byte i = 0; i < ITERATIONS; i++) {
final byte[] hash = HashUtil.sha3(new byte[]{i});
sigFutures.add(executor.submit(new Callable<ECDSASignature>() {
@Override
public ECKey.ECDSASignature call() throws Exception {
return key.doSign(hash);
}
}));
}
List<ECKey.ECDSASignature> sigs = Futures.allAsList(sigFutures).get();
for (ECKey.ECDSASignature signature : sigs) {
assertTrue(signature.s.compareTo(ECKey.HALF_CURVE_ORDER) <= 0);
}
final ECKey.ECDSASignature duplicate = new ECKey.ECDSASignature(sigs.get(0).r, sigs.get(0).s);
assertEquals(sigs.get(0), duplicate);
assertEquals(sigs.get(0).hashCode(), duplicate.hashCode());
}
@Test
public void testSignVerify() {
ECKey key = ECKey.fromPrivate(privateKey);
String message = new String("This is an example of a signed message.");
ECDSASignature output = key.doSign(message.getBytes());
assertTrue(key.verify(message.getBytes(), output));
}
@Test
public void testIsPubKeyCanonicalCorect() {
// Test correct prefix 4, right length 65
byte[] canonicalPubkey1 = new byte[65];
canonicalPubkey1[0] = 0x04;
assertTrue(ECKey.isPubKeyCanonical(canonicalPubkey1));
// Test correct prefix 2, right length 33
byte[] canonicalPubkey2 = new byte[33];
canonicalPubkey2[0] = 0x02;
assertTrue(ECKey.isPubKeyCanonical(canonicalPubkey2));
// Test correct prefix 3, right length 33
byte[] canonicalPubkey3 = new byte[33];
canonicalPubkey3[0] = 0x03;
assertTrue(ECKey.isPubKeyCanonical(canonicalPubkey3));
}
@Test
public void testIsPubKeyCanonicalWrongLength() {
// Test correct prefix 4, but wrong length !65
byte[] nonCanonicalPubkey1 = new byte[64];
nonCanonicalPubkey1[0] = 0x04;
assertFalse(ECKey.isPubKeyCanonical(nonCanonicalPubkey1));
// Test correct prefix 2, but wrong length !33
byte[] nonCanonicalPubkey2 = new byte[32];
nonCanonicalPubkey2[0] = 0x02;
assertFalse(ECKey.isPubKeyCanonical(nonCanonicalPubkey2));
// Test correct prefix 3, but wrong length !33
byte[] nonCanonicalPubkey3 = new byte[32];
nonCanonicalPubkey3[0] = 0x03;
assertFalse(ECKey.isPubKeyCanonical(nonCanonicalPubkey3));
}
@Test
public void testIsPubKeyCanonicalWrongPrefix() {
// Test wrong prefix 4, right length 65
byte[] nonCanonicalPubkey4 = new byte[65];
assertFalse(ECKey.isPubKeyCanonical(nonCanonicalPubkey4));
// Test wrong prefix 2, right length 33
byte[] nonCanonicalPubkey5 = new byte[33];
assertFalse(ECKey.isPubKeyCanonical(nonCanonicalPubkey5));
// Test wrong prefix 3, right length 33
byte[] nonCanonicalPubkey6 = new byte[33];
assertFalse(ECKey.isPubKeyCanonical(nonCanonicalPubkey6));
}
@Test
public void keyRecovery() throws Exception {
ECKey key = new ECKey();
String message = "Hello World!";
byte[] hash = HashUtil.sha256(message.getBytes());
ECKey.ECDSASignature sig = key.doSign(hash);
key = ECKey.fromPublicOnly(key.getPubKeyPoint());
boolean found = false;
for (int i = 0; i < 4; i++) {
ECKey key2 = ECKey.recoverFromSignature(i, sig, hash, true);
checkNotNull(key2);
if (key.equals(key2)) {
found = true;
break;
}
}
assertTrue(found);
}
@Test
public void testSignedMessageToKey() throws SignatureException {
byte[] messageHash = HashUtil.sha3(exampleMessage.getBytes());
ECKey key = ECKey.signatureToKey(messageHash, sigBase64);
assertNotNull(key);
assertArrayEquals(pubKey, key.getPubKey());
}
@Test
public void testGetPrivKeyBytes() {
ECKey key = new ECKey();
assertNotNull(key.getPrivKeyBytes());
assertEquals(32, key.getPrivKeyBytes().length);
}
@Test
public void testEqualsObject() {
ECKey key0 = new ECKey();
ECKey key1 = ECKey.fromPrivate(privateKey);
ECKey key2 = ECKey.fromPrivate(privateKey);
assertFalse(key0.equals(key1));
assertTrue(key1.equals(key1));
assertTrue(key1.equals(key2));
}
}

View File

@ -1,58 +0,0 @@
package test.ethereum.datasource;
import org.ethereum.datasource.redis.RedisConnection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import org.springframework.util.StringUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Protocol;
import test.ethereum.TestContext;
import java.net.URI;
import java.net.URISyntaxException;
import static org.junit.Assert.assertFalse;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public abstract class AbstractRedisTest {
@Configuration
@ComponentScan(basePackages = "org.ethereum")
static class ContextConfiguration extends TestContext { }
@Autowired
private RedisConnection redisConnection;
private Boolean connected;
protected RedisConnection getRedisConnection() {
return redisConnection;
}
protected Boolean isConnected() {
if (connected == null) {
String url = System.getenv(RedisConnection.REDISCLOUD_URL);
try {
Jedis jedis = new Jedis(new URI(url));
connected = jedis.ping().equals("PONG");
jedis.close();
} catch (Exception e) {
System.out.printf("Cannot connect to '%s' Redis cloud.\n", url);
}
assertFalse(connected ^ redisConnection.isAvailable());
}
return connected;
}
}

View File

@ -1,75 +0,0 @@
package test.ethereum.datasource;
import org.ethereum.datasource.KeyValueDataSource;
import org.ethereum.datasource.redis.RedisConnection;
import org.ethereum.datasource.redis.RedisDataSource;
import org.junit.Assert;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
import redis.clients.jedis.Jedis;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Set;
/**
* @author Roman Mandeleil
*/
public class RedisDataSourceTest extends AbstractRedisTest {
@Test
public void testSet1() {
if (!isConnected()) return;
KeyValueDataSource dataSource = createDataSource("test-state");
try {
byte[] key = Hex.decode("a1a2a3");
byte[] val = Hex.decode("b1b2b3");
dataSource.put(key, val);
byte[] val2 = dataSource.get(key);
Assert.assertEquals(Hex.toHexString(val), Hex.toHexString(val2));
} finally {
clear(dataSource);
}
}
@Test
public void testSet2() {
if (!isConnected()) return;
KeyValueDataSource states = createDataSource("test-state");
KeyValueDataSource details = createDataSource("test-details");
try {
byte[] key = Hex.decode("a1a2a3");
byte[] val1 = Hex.decode("b1b2b3");
byte[] val2 = Hex.decode("c1c2c3");
states.put(key, val1);
details.put(key, val2);
byte[] res1 = states.get(key);
byte[] res2 = details.get(key);
Assert.assertEquals(Hex.toHexString(val1), Hex.toHexString(res1));
Assert.assertEquals(Hex.toHexString(val2), Hex.toHexString(res2));
} finally {
clear(states);
clear(details);
}
}
private KeyValueDataSource createDataSource(String name) {
KeyValueDataSource result = getRedisConnection().createDataSource(name);
result.setName(name);
result.init();
return result;
}
private void clear(KeyValueDataSource dataSource) {
((RedisDataSource) dataSource).clear();
}
}

View File

@ -1,130 +0,0 @@
package test.ethereum.datasource;
import org.ethereum.core.Transaction;
import org.ethereum.crypto.ECKey;
import org.ethereum.crypto.HashUtil;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.util.Set;
import static java.util.Arrays.asList;
import static org.junit.Assert.*;
public class RedisStorageTest extends AbstractRedisTest {
@Test
public void testRedisSet() {
if (!isConnected()) return;
Pojo elephant = Pojo.create(5L, "elephant");
Pojo lion = Pojo.create(5L, "lion");
Set<Pojo> ranch = getRedisConnection().createSetFor(Pojo.class, "ranch");
Pojo chicken = Pojo.create(1L, "chicken");
Pojo cow = Pojo.create(2L, "cow");
Pojo puppy = Pojo.create(3L, "puppy");
Pojo kitten = Pojo.create(4L, "kitten");
assertTrue(ranch.add(chicken));
assertFalse(ranch.add(chicken));
assertTrue(ranch.contains(chicken));
assertEquals(1, ranch.size());
Pojo next = ranch.iterator().next();
assertNotNull(next);
assertEquals(chicken, next);
assertTrue(ranch.addAll(asList(cow, puppy, kitten)));
assertEquals(4, ranch.size());
assertFalse(ranch.isEmpty());
assertFalse(ranch.remove(elephant));
assertFalse(ranch.removeAll(asList(cow, lion, elephant)));
assertEquals(3, ranch.size());
assertTrue(ranch.retainAll(asList(kitten, puppy)));
assertEquals(2, ranch.size());
ranch.clear();
assertEquals(0, ranch.size());
assertTrue(ranch.isEmpty());
}
@Test
public void testSeveralSetsWithOneName() {
if (!isConnected()) return;
final String name = "testTransactions";
Set<Transaction> transactions = getRedisConnection().createTransactionSet(name);
transactions.add(createTransaction("09184e72a000", "4255", "1000000000000000000000", "cat"));
transactions.add(createTransaction("09184e72a000", "4255", "1000000000000000000000", "dog"));
transactions.add(createTransaction("09184e72a000", "4255", "1000000000000000000000", "rabbit"));
Set<Transaction> transactions1 = getRedisConnection().createTransactionSet(name);
transactions1.add(createTransaction("09184e72a000", "4255", "1000000000000000000000", "duck"));
transactions1.add(createTransaction("09184e72a000", "4255", "1000000000000000000000", "chicken"));
transactions1.add(createTransaction("09184e72a000", "4255", "1000000000000000000000", "cow"));
assertEquals(6, transactions1.size());
transactions.clear();
assertTrue(transactions1.isEmpty());
}
private static class Pojo {
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static Pojo create(long id, String name) {
Pojo result = new Pojo();
result.setId(id);
result.setName(name);
return result;
}
@Override
public boolean equals(Object obj) {
if (obj == null || !getClass().isInstance(obj)) return false;
if (this == obj) return true;
Pojo another = (Pojo) obj;
return (another.getId() == getId()) && another.getName().equals(getName());
}
@Override
public int hashCode() {
int hashCode = 17;
hashCode += ((getId() == null) ? 0 : getId().hashCode()) * 31;
hashCode += ((getName() == null) ? 0 : getName().hashCode()) * 31;
return hashCode;
}
}
public static Transaction createTransaction(String gasPrice, String gas, String val, String secret) {
ECKey ecKey = ECKey.fromPrivate(HashUtil.sha3(secret.getBytes()));
// Tn (nonce); Tp(pgas); Tg(gaslimi); Tt(value); Tv(value); Ti(sender); Tw; Tr; Ts
return new Transaction(null, Hex.decode(gasPrice), Hex.decode(gas), ecKey.getAddress(),
new BigInteger(val).toByteArray(),
null);
}
}

View File

@ -1,144 +0,0 @@
package test.ethereum.db;
import org.ethereum.db.ByteArrayWrapper;
import org.ethereum.util.FastByteComparisons;
import com.google.common.primitives.UnsignedBytes;
import org.junit.BeforeClass;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
import java.util.Arrays;
import java.util.Comparator;
import static org.junit.Assert.*;
public class ByteArrayWrapperTest {
static ByteArrayWrapper wrapper1;
static ByteArrayWrapper wrapper2;
static ByteArrayWrapper wrapper3;
static ByteArrayWrapper wrapper4;
@BeforeClass
public static void loadByteArrays() {
String block = "f9072df8d3a077ef4fdaf389dca53236bcf7f72698e154eab2828f86fbc4fc6c"
+ "d9225d285c89a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0"
+ "a142fd40d493479476f5eabe4b342ee56b8ceba6ab2a770c3e2198e7a0faa0ca"
+ "43105f667dceb168eb4e0cdc98ef28a9da5c381edef70d843207601719a06785"
+ "f3860460b2aa29122698e83a5151b270e82532c1663e89e3df8c5445b8ca833f"
+ "f000018609184e72a000830f3e6f8227d2845387c58f80a00000000000000000"
+ "0000000000000000000000000000000094148d7738f78c04f90654f8c6f8a080"
+ "8609184e72a00082271094000000000000000000000000000000000000000080"
+ "b83a33604557602a5160106000396000f200604556330e0f602a59366000530a"
+ "0f602a596020600053013560005335576040600053016000546009581ca033a6"
+ "bfa5eb2f4b63f1b98bed9a987d096d32e56deecb050367c84955508f5365a015"
+ "034e7574ec073f0c448aac1d9f844387610dfef5342834b6825fbc35df5913a0"
+ "ee258e73d41ada73d8d6071ba7d236fbbe24fcfb9627fbd4310e24ffd87b961a"
+ "8203e9f90194f9016d018609184e72a000822710940000000000000000000000"
+ "00000000000000000080b901067f4e616d655265670000000000000000000000"
+ "00000000000000000000000000003057307f4e616d6552656700000000000000"
+ "000000000000000000000000000000000000577f436f6e666967000000000000"
+ "000000000000000000000000000000000000000073ccdeac59d35627b7de0933"
+ "2e819d5159e7bb72505773ccdeac59d35627b7de09332e819d5159e7bb72507f"
+ "436f6e6669670000000000000000000000000000000000000000000000000000"
+ "57336045576041516100c56000396000f20036602259604556330e0f600f5933"
+ "ff33560f601e5960003356576000335700604158600035560f602b590033560f"
+ "603659600033565733600035576000353357001ca0f3c527e484ea5546189979"
+ "c767b69aa9f1ad5a6f4b6077d4bccf5142723a67c9a069a4a29a2a315102fcd0"
+ "822d39ad696a6d7988c993bb2b911cc2a78bb8902d91a01ebe4782ea3ed224cc"
+ "bb777f5de9ee7b5bbb282ac08f7fa0ef95d3d1c1c6d1a1820ef7f8ccf8a60286"
+ "09184e72a00082271094ccdeac59d35627b7de09332e819d5159e7bb725080b8"
+ "4000000000000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000000002d0aceee7e5ab874e22ccf8d1a649f59106d74"
+ "e81ba095ad45bf574c080e4d72da2cfd3dbe06cc814c1c662b5f74561f13e1e7"
+ "5058f2a057745a3db5482bccb5db462922b074f4b79244c4b1fa811ed094d728"
+ "e7b6da92a08599ea5d6cb6b9ad3311f0d82a3337125e05f4a82b9b0556cb3776"
+ "a6e1a02f8782132df8abf885038609184e72a000822710942d0aceee7e5ab874"
+ "e22ccf8d1a649f59106d74e880a0476176000000000000000000000000000000"
+ "00000000000000000000000000001ca09b5fdabd54ebc284249d2d2df6d43875"
+ "cb86c52bd2bac196d4f064c8ade054f2a07b33f5c8b277a408ec38d2457441d2"
+ "af32e55681c8ecb28eef3d2a152e8db5a9a0227a67fceb1bf4ddd31a7047e24b"
+ "e93c947ab3b539471555bb3509ed6e393c8e82178df90277f90250048609184e"
+ "72a0008246dd94000000000000000000000000000000000000000080b901e961"
+ "010033577f476176436f696e0000000000000000000000000000000000000000"
+ "000000000060005460006000600760006000732d0aceee7e5ab874e22ccf8d1a"
+ "649f59106d74e860645c03f150436000576000600157620f424060025761017d"
+ "5161006c6000396000f2006020360e0f61013f59602060006000374360205460"
+ "0056600054602056602054437f6e000000000000000000000000000000000000"
+ "00000000000000000000000000560e0f0f61008059437f6e0000000000000000"
+ "0000000000000000000000000000000000000000000000576000602054610400"
+ "60005304600053036000547f6400000000000000000000000000000000000000"
+ "0000000000000000000000005660016000030460406000200a0f61013e596001"
+ "60205301602054600a6020530b0f6100f45961040060005304600053017f6400"
+ "0000000000000000000000000000000000000000000000000000000000005760"
+ "20537f6900000000000000000000000000000000000000000000000000000000"
+ "000000576000537f640000000000000000000000000000000000000000000000"
+ "000000000000000057006040360e0f0f61014a59003356604054600035566060"
+ "546020356080546080536040530a0f6101695900608053604053033357608053"
+ "60605301600035571ba0190fc7ab634dc497fe1656fde523a4c26926d51a93db"
+ "2ba37af8e83c3741225da066ae0ec1217b0ca698a5369d4881e1c4cbde56af99"
+ "31ebf9281580a23b659c08a051f947cb2315d0259f55848c630caa10cd91d6e4"
+ "4ff8bad7758c65b25e2191308227d2c0";
byte[] test1 = Hex.decode(block);
byte[] test2 = Hex.decode(block);
byte[] test3 = Hex.decode("4ff8bad7758c65b25e2191308227d2c0");
byte[] test4 = Hex.decode("");
wrapper1 = new ByteArrayWrapper(test1);
wrapper2 = new ByteArrayWrapper(test2);
wrapper3 = new ByteArrayWrapper(test3);
wrapper4 = new ByteArrayWrapper(test4);
}
@Test
public void testEqualsObject() {
assertTrue(wrapper1.equals(wrapper2));
assertFalse(wrapper1.equals(wrapper3));
assertFalse(wrapper1.equals(wrapper4));
assertFalse(wrapper1.equals(null));
assertFalse(wrapper2.equals(wrapper3));
}
@Test
public void testCompareTo() {
assertTrue(wrapper1.compareTo(wrapper2) == 0);
assertTrue(wrapper1.compareTo(wrapper3) > 1);
assertTrue(wrapper1.compareTo(wrapper4) > 1);
assertTrue(wrapper2.compareTo(wrapper3) > 1);
}
@Test
public void testEqualsPerformance() {
boolean testEnabled = false;
if (testEnabled) {
final int ITERATIONS = 10000000;
long start1 = System.currentTimeMillis();
for (int i = 0; i < ITERATIONS; i++) {
Comparator<byte[]> comparator = UnsignedBytes
.lexicographicalComparator();
comparator.compare(wrapper1.getData(),
wrapper2.getData());
}
System.out.println(System.currentTimeMillis() - start1 + "ms");
long start2 = System.currentTimeMillis();
for (int i = 0; i < ITERATIONS; i++) {
Arrays.equals(wrapper1.getData(), wrapper2.getData());
}
System.out.println(System.currentTimeMillis() - start2 + "ms");
long start3 = System.currentTimeMillis();
for (int i = 0; i < ITERATIONS; i++) {
FastByteComparisons.compareTo(wrapper1.getData(), 0, wrapper1.getData().length, wrapper2.getData(), 0, wrapper1.getData().length);
}
System.out.println(System.currentTimeMillis() - start3 + "ms");
}
}
}

View File

@ -1,67 +0,0 @@
package test.ethereum.db;
import org.ethereum.datasource.KeyValueDataSource;
import org.ethereum.db.ByteArrayWrapper;
import org.iq80.leveldb.DBException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MockDB implements KeyValueDataSource {
Map<ByteArrayWrapper, byte[]> storage = new HashMap<>();
@Override
public void delete(byte[] arg0) throws DBException {
storage.remove(arg0);
}
@Override
public byte[] get(byte[] arg0) throws DBException {
return storage.get(new ByteArrayWrapper(arg0));
}
@Override
public byte[] put(byte[] key, byte[] value) throws DBException {
return storage.put(new ByteArrayWrapper(key), value);
}
/**
* Returns the number of items added to this Mock DB
*
* @return int
*/
public int getAddedItems() {
return storage.size();
}
@Override
public void init() {
}
@Override
public void setName(String name) {
}
@Override
public Set<byte[]> keys() {
return null;
}
@Override
public void updateBatch(Map<byte[], byte[]> rows) {
}
@Override
public void close() {
}
}

View File

@ -1,531 +0,0 @@
package test.ethereum.db;
import org.ethereum.config.SystemProperties;
import org.ethereum.core.Genesis;
import org.ethereum.core.PremineRaw;
import org.ethereum.crypto.HashUtil;
import org.ethereum.datasource.LevelDbDataSource;
import org.ethereum.db.RepositoryImpl;
import org.ethereum.facade.Repository;
import org.ethereum.vm.DataWord;
import org.junit.Assert;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import static org.junit.Assert.*;
/**
* @author Roman Mandeleil
* @since 17.11.2014
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class RepositoryTest {
@Test
public void test1() {
SystemProperties.CONFIG.setDataBaseDir("test_db/" + RepositoryTest.class);
Repository repository = new RepositoryImpl(new LevelDbDataSource(), new LevelDbDataSource());
byte[] cow = Hex.decode("CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826");
byte[] horse = Hex.decode("13978AEE95F38490E9769C39B2773ED763D9CD5F");
repository.increaseNonce(cow);
repository.increaseNonce(horse);
assertEquals(BigInteger.ONE, repository.getNonce(cow));
assertEquals(BigInteger.ONE, repository.getNonce(horse));
repository.close();
}
@Test
public void test2() {
SystemProperties.CONFIG.setDataBaseDir("test_db/" + RepositoryTest.class);
Repository repository = new RepositoryImpl(new LevelDbDataSource(), new LevelDbDataSource());
byte[] cow = Hex.decode("CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826");
byte[] horse = Hex.decode("13978AEE95F38490E9769C39B2773ED763D9CD5F");
repository.addBalance(cow, BigInteger.TEN);
repository.addBalance(horse, BigInteger.ONE);
assertEquals(BigInteger.TEN, repository.getBalance(cow));
assertEquals(BigInteger.ONE, repository.getBalance(horse));
repository.close();
}
@Test
public void test3() {
SystemProperties.CONFIG.setDataBaseDir("test_db/" + RepositoryTest.class);
Repository repository = new RepositoryImpl(new LevelDbDataSource(), new LevelDbDataSource());
byte[] cow = Hex.decode("CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826");
byte[] horse = Hex.decode("13978AEE95F38490E9769C39B2773ED763D9CD5F");
byte[] cowCode = Hex.decode("A1A2A3");
byte[] horseCode = Hex.decode("B1B2B3");
repository.saveCode(cow, cowCode);
repository.saveCode(horse, horseCode);
assertArrayEquals(cowCode, repository.getCode(cow));
assertArrayEquals(horseCode, repository.getCode(horse));
repository.close();
}
@Test
public void test4() {
SystemProperties.CONFIG.setDataBaseDir("test_db/" + RepositoryTest.class);
Repository repository = new RepositoryImpl(new LevelDbDataSource(), new LevelDbDataSource());
byte[] cow = Hex.decode("CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826");
byte[] horse = Hex.decode("13978AEE95F38490E9769C39B2773ED763D9CD5F");
byte[] cowKey = Hex.decode("A1A2A3");
byte[] cowValue = Hex.decode("A4A5A6");
byte[] horseKey = Hex.decode("B1B2B3");
byte[] horseValue = Hex.decode("B4B5B6");
repository.addStorageRow(cow, new DataWord(cowKey), new DataWord(cowValue));
repository.addStorageRow(horse, new DataWord(horseKey), new DataWord(horseValue));
assertEquals(new DataWord(cowValue), repository.getStorageValue(cow, new DataWord(cowKey)));
assertEquals(new DataWord(horseValue), repository.getStorageValue(horse, new DataWord(horseKey)));
repository.close();
}
@Test
public void test5() {
SystemProperties.CONFIG.setDataBaseDir("test_db/" + RepositoryTest.class);
Repository repository = new RepositoryImpl(new LevelDbDataSource(), new LevelDbDataSource());
Repository track = repository.startTracking();
byte[] cow = Hex.decode("CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826");
byte[] horse = Hex.decode("13978AEE95F38490E9769C39B2773ED763D9CD5F");
track.increaseNonce(cow);
track.increaseNonce(cow);
track.increaseNonce(cow);
track.increaseNonce(cow);
track.increaseNonce(cow);
track.increaseNonce(cow);
track.increaseNonce(cow);
track.increaseNonce(cow);
track.increaseNonce(cow);
track.increaseNonce(cow);
track.increaseNonce(horse);
track.commit();
assertEquals(BigInteger.TEN, repository.getNonce(cow));
assertEquals(BigInteger.ONE, repository.getNonce(horse));
repository.close();
}
@Test
public void test6() {
SystemProperties.CONFIG.setDataBaseDir("test_db/" + RepositoryTest.class);
Repository repository = new RepositoryImpl(new LevelDbDataSource(), new LevelDbDataSource());
Repository track = repository.startTracking();
byte[] cow = Hex.decode("CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826");
byte[] horse = Hex.decode("13978AEE95F38490E9769C39B2773ED763D9CD5F");
track.increaseNonce(cow);
track.increaseNonce(cow);
track.increaseNonce(cow);
track.increaseNonce(cow);
track.increaseNonce(cow);
track.increaseNonce(cow);
track.increaseNonce(cow);
track.increaseNonce(cow);
track.increaseNonce(cow);
track.increaseNonce(cow);
track.increaseNonce(horse);
assertEquals(BigInteger.TEN, track.getNonce(cow));
assertEquals(BigInteger.ONE, track.getNonce(horse));
track.rollback();
assertEquals(BigInteger.ZERO, repository.getNonce(cow));
assertEquals(BigInteger.ZERO, repository.getNonce(horse));
repository.close();
}
@Test
public void test7() {
SystemProperties.CONFIG.setDataBaseDir("test_db/" + RepositoryTest.class);
Repository repository = new RepositoryImpl(new LevelDbDataSource(), new LevelDbDataSource());
Repository track = repository.startTracking();
byte[] cow = Hex.decode("CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826");
byte[] horse = Hex.decode("13978AEE95F38490E9769C39B2773ED763D9CD5F");
track.addBalance(cow, BigInteger.TEN);
track.addBalance(horse, BigInteger.ONE);
assertEquals(BigInteger.TEN, track.getBalance(cow));
assertEquals(BigInteger.ONE, track.getBalance(horse));
track.commit();
assertEquals(BigInteger.TEN, repository.getBalance(cow));
assertEquals(BigInteger.ONE, repository.getBalance(horse));
repository.close();
}
@Test
public void test8() {
SystemProperties.CONFIG.setDataBaseDir("test_db/" + RepositoryTest.class);
Repository repository = new RepositoryImpl(new LevelDbDataSource(), new LevelDbDataSource());
Repository track = repository.startTracking();
byte[] cow = Hex.decode("CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826");
byte[] horse = Hex.decode("13978AEE95F38490E9769C39B2773ED763D9CD5F");
track.addBalance(cow, BigInteger.TEN);
track.addBalance(horse, BigInteger.ONE);
assertEquals(BigInteger.TEN, track.getBalance(cow));
assertEquals(BigInteger.ONE, track.getBalance(horse));
track.rollback();
assertEquals(BigInteger.ZERO, repository.getBalance(cow));
assertEquals(BigInteger.ZERO, repository.getBalance(horse));
repository.close();
}
@Test
public void test9() {
SystemProperties.CONFIG.setDataBaseDir("test_db/" + RepositoryTest.class);
Repository repository = new RepositoryImpl(new LevelDbDataSource(), new LevelDbDataSource());
Repository track = repository.startTracking();
byte[] cow = Hex.decode("CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826");
byte[] horse = Hex.decode("13978AEE95F38490E9769C39B2773ED763D9CD5F");
DataWord cowKey = new DataWord(Hex.decode("A1A2A3"));
DataWord cowValue = new DataWord(Hex.decode("A4A5A6"));
DataWord horseKey = new DataWord(Hex.decode("B1B2B3"));
DataWord horseValue = new DataWord(Hex.decode("B4B5B6"));
track.addStorageRow(cow, cowKey, cowValue);
track.addStorageRow(horse, horseKey, horseValue);
assertEquals(cowValue, track.getStorageValue(cow, cowKey));
assertEquals(horseValue, track.getStorageValue(horse, horseKey));
track.commit();
assertEquals(cowValue, repository.getStorageValue(cow, cowKey));
assertEquals(horseValue, repository.getStorageValue(horse, horseKey));
repository.close();
}
@Test
public void test10() {
SystemProperties.CONFIG.setDataBaseDir("test_db/" + RepositoryTest.class);
Repository repository = new RepositoryImpl(new LevelDbDataSource(), new LevelDbDataSource());
Repository track = repository.startTracking();
byte[] cow = Hex.decode("CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826");
byte[] horse = Hex.decode("13978AEE95F38490E9769C39B2773ED763D9CD5F");
DataWord cowKey = new DataWord(Hex.decode("A1A2A3"));
DataWord cowValue = new DataWord(Hex.decode("A4A5A6"));
DataWord horseKey = new DataWord(Hex.decode("B1B2B3"));
DataWord horseValue = new DataWord(Hex.decode("B4B5B6"));
track.addStorageRow(cow, cowKey, cowValue);
track.addStorageRow(horse, horseKey, horseValue);
assertEquals(cowValue, track.getStorageValue(cow, cowKey));
assertEquals(horseValue, track.getStorageValue(horse, horseKey));
track.rollback();
assertEquals(null, repository.getStorageValue(cow, cowKey));
assertEquals(null, repository.getStorageValue(horse, horseKey));
repository.close();
}
@Test
public void test11() {
SystemProperties.CONFIG.setDataBaseDir("test_db/" + RepositoryTest.class);
Repository repository = new RepositoryImpl(new LevelDbDataSource(), new LevelDbDataSource());
Repository track = repository.startTracking();
byte[] cow = Hex.decode("CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826");
byte[] horse = Hex.decode("13978AEE95F38490E9769C39B2773ED763D9CD5F");
byte[] cowCode = Hex.decode("A1A2A3");
byte[] horseCode = Hex.decode("B1B2B3");
track.saveCode(cow, cowCode);
track.saveCode(horse, horseCode);
assertArrayEquals(cowCode, track.getCode(cow));
assertArrayEquals(horseCode, track.getCode(horse));
track.commit();
assertArrayEquals(cowCode, repository.getCode(cow));
assertArrayEquals(horseCode, repository.getCode(horse));
repository.close();
}
@Test
public void test12() {
SystemProperties.CONFIG.setDataBaseDir("test_db/" + RepositoryTest.class);
Repository repository = new RepositoryImpl(new LevelDbDataSource(), new LevelDbDataSource());
Repository track = repository.startTracking();
byte[] cow = Hex.decode("CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826");
byte[] horse = Hex.decode("13978AEE95F38490E9769C39B2773ED763D9CD5F");
byte[] cowCode = Hex.decode("A1A2A3");
byte[] horseCode = Hex.decode("B1B2B3");
track.saveCode(cow, cowCode);
track.saveCode(horse, horseCode);
assertArrayEquals(cowCode, track.getCode(cow));
assertArrayEquals(horseCode, track.getCode(horse));
track.rollback();
assertArrayEquals(null, repository.getCode(cow));
assertArrayEquals(null, repository.getCode(horse));
repository.close();
}
@Test // Let's upload genesis pre-mine just like in the real world
public void test13() {
SystemProperties.CONFIG.setDataBaseDir("test_db/" + RepositoryTest.class);
Repository repository = new RepositoryImpl(new LevelDbDataSource(), new LevelDbDataSource());
Repository track = repository.startTracking();
for (PremineRaw raw : Genesis.getPremine()) {
track.addBalance(raw.getAddr(), raw.getValue().multiply(raw.getDenomination().value()));
}
track.commit();
assertArrayEquals(Genesis.getInstance().getStateRoot(), repository.getRoot());
repository.close();
}
@Test
public void test14() {
SystemProperties.CONFIG.setDataBaseDir("test_db/" + RepositoryTest.class);
Repository repository = new RepositoryImpl(new LevelDbDataSource(), new LevelDbDataSource());
byte[] cow = Hex.decode("CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826");
byte[] horse = Hex.decode("13978AEE95F38490E9769C39B2773ED763D9CD5F");
final BigInteger ELEVEN = BigInteger.TEN.add(BigInteger.ONE);
// changes level_1
Repository track1 = repository.startTracking();
track1.addBalance(cow, BigInteger.TEN);
track1.addBalance(horse, BigInteger.ONE);
assertEquals(BigInteger.TEN, track1.getBalance(cow));
assertEquals(BigInteger.ONE, track1.getBalance(horse));
// changes level_2
Repository track2 = track1.startTracking();
track2.addBalance(cow, BigInteger.ONE);
track2.addBalance(horse, BigInteger.TEN);
assertEquals(ELEVEN, track2.getBalance(cow));
assertEquals(ELEVEN, track2.getBalance(horse));
track2.commit();
track1.commit();
assertEquals(ELEVEN, repository.getBalance(cow));
assertEquals(ELEVEN, repository.getBalance(horse));
repository.close();
}
@Test
public void test15() {
SystemProperties.CONFIG.setDataBaseDir("test_db/" + RepositoryTest.class);
Repository repository = new RepositoryImpl(new LevelDbDataSource(), new LevelDbDataSource());
byte[] cow = Hex.decode("CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826");
byte[] horse = Hex.decode("13978AEE95F38490E9769C39B2773ED763D9CD5F");
final BigInteger ELEVEN = BigInteger.TEN.add(BigInteger.ONE);
// changes level_1
Repository track1 = repository.startTracking();
track1.addBalance(cow, BigInteger.TEN);
track1.addBalance(horse, BigInteger.ONE);
assertEquals(BigInteger.TEN, track1.getBalance(cow));
assertEquals(BigInteger.ONE, track1.getBalance(horse));
// changes level_2
Repository track2 = track1.startTracking();
track2.addBalance(cow, BigInteger.ONE);
track2.addBalance(horse, BigInteger.TEN);
assertEquals(ELEVEN, track2.getBalance(cow));
assertEquals(ELEVEN, track2.getBalance(horse));
track2.rollback();
track1.commit();
assertEquals(BigInteger.TEN, repository.getBalance(cow));
assertEquals(BigInteger.ONE, repository.getBalance(horse));
repository.close();
}
@Test
public void test16() {
SystemProperties.CONFIG.setDataBaseDir("test_db/" + RepositoryTest.class);
Repository repository = new RepositoryImpl(new LevelDbDataSource(), new LevelDbDataSource());
byte[] cow = Hex.decode("CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826");
byte[] horse = Hex.decode("13978AEE95F38490E9769C39B2773ED763D9CD5F");
byte[] cowKey1 = "key-c-1".getBytes();
byte[] cowValue1 = "val-c-1".getBytes();
byte[] horseKey1 = "key-h-1".getBytes();
byte[] horseValue1 = "val-h-1".getBytes();
byte[] cowKey2 = "key-c-2".getBytes();
byte[] cowValue2 = "val-c-2".getBytes();
byte[] horseKey2 = "key-h-2".getBytes();
byte[] horseValue2 = "val-h-2".getBytes();
// changes level_1
Repository track1 = repository.startTracking();
track1.addStorageRow(cow, new DataWord(cowKey1), new DataWord(cowValue1));
track1.addStorageRow(horse, new DataWord(horseKey1), new DataWord(horseValue1));
assertEquals(new DataWord(cowValue1), track1.getStorageValue(cow, new DataWord(cowKey1)));
assertEquals(new DataWord(horseValue1), track1.getStorageValue(horse, new DataWord(horseKey1)));
// changes level_2
Repository track2 = track1.startTracking();
track2.addStorageRow(cow, new DataWord(cowKey2), new DataWord(cowValue2));
track2.addStorageRow(horse, new DataWord(horseKey2), new DataWord(horseValue2));
assertEquals(new DataWord(cowValue1), track2.getStorageValue(cow, new DataWord(cowKey1)));
assertEquals(new DataWord(horseValue1), track2.getStorageValue(horse, new DataWord(horseKey1)));
assertEquals(new DataWord(cowValue2), track2.getStorageValue(cow, new DataWord(cowKey2)));
assertEquals(new DataWord(horseValue2), track2.getStorageValue(horse, new DataWord(horseKey2)));
track2.commit();
// leaving level_2
assertEquals(new DataWord(cowValue1), track1.getStorageValue(cow, new DataWord(cowKey1)));
assertEquals(new DataWord(horseValue1), track1.getStorageValue(horse, new DataWord(horseKey1)));
assertEquals(new DataWord(cowValue2), track1.getStorageValue(cow, new DataWord(cowKey2)));
assertEquals(new DataWord(horseValue2), track1.getStorageValue(horse, new DataWord(horseKey2)));
track1.commit();
// leaving level_1
assertEquals(new DataWord(cowValue1), repository.getStorageValue(cow, new DataWord(cowKey1)));
assertEquals(new DataWord(horseValue1), repository.getStorageValue(horse, new DataWord(horseKey1)));
assertEquals(new DataWord(cowValue2), repository.getStorageValue(cow, new DataWord(cowKey2)));
assertEquals(new DataWord(horseValue2), repository.getStorageValue(horse, new DataWord(horseKey2)));
repository.close();
}
@Test
public void test17() {
SystemProperties.CONFIG.setDataBaseDir("test_db/" + RepositoryTest.class);
Repository repository = new RepositoryImpl(new LevelDbDataSource(), new LevelDbDataSource());
byte[] cow = Hex.decode("CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826");
byte[] cowKey1 = "key-c-1".getBytes();
byte[] cowValue1 = "val-c-1".getBytes();
// changes level_1
Repository track1 = repository.startTracking();
// changes level_2
Repository track2 = track1.startTracking();
track2.addStorageRow(cow, new DataWord(cowKey1), new DataWord(cowValue1));
assertEquals(new DataWord(cowValue1), track2.getStorageValue(cow, new DataWord(cowKey1)));
track2.rollback();
// leaving level_2
track1.commit();
// leaving level_1
Assert.assertEquals(Hex.toHexString(HashUtil.EMPTY_TRIE_HASH), Hex.toHexString(repository.getRoot()));
repository.close();
}
}

View File

@ -1,67 +0,0 @@
package test.ethereum.db;
import org.ethereum.datasource.KeyValueDataSource;
import org.ethereum.datasource.LevelDbDataSource;
import org.ethereum.db.DatabaseImpl;
import org.ethereum.db.TrackDatabase;
import org.iq80.leveldb.Options;
import org.junit.AfterClass;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
import java.io.File;
import java.io.IOException;
import static org.iq80.leveldb.impl.Iq80DBFactory.factory;
import static org.junit.Assert.*;
/**
* @author Roman Mandeleil
* @since 11.06.2014
*/
public class TrackDatabaseTest {
@Test
public void test1() {
KeyValueDataSource keyValueDataSource = new LevelDbDataSource("temp");
keyValueDataSource.init();
DatabaseImpl db1 = new DatabaseImpl(keyValueDataSource);
TrackDatabase trackDatabase1 = new TrackDatabase(db1);
trackDatabase1.put(Hex.decode("abcdef"), Hex.decode("abcdef"));
byte[] value = trackDatabase1.get(Hex.decode("abcdef"));
assertEquals("abcdef", Hex.toHexString(value));
trackDatabase1.startTrack();
trackDatabase1.put(Hex.decode("abcdef"), Hex.decode("ffffff"));
value = trackDatabase1.get(Hex.decode("abcdef"));
assertEquals("ffffff", Hex.toHexString(value));
trackDatabase1.rollbackTrack();
value = trackDatabase1.get(Hex.decode("abcdef"));
assertEquals("abcdef", Hex.toHexString(value));
trackDatabase1.startTrack();
trackDatabase1.put(Hex.decode("abcdef"), Hex.decode("ffffff"));
trackDatabase1.commitTrack();
value = trackDatabase1.get(Hex.decode("abcdef"));
assertEquals("ffffff", Hex.toHexString(value));
db1.close();
}
@AfterClass
public static void destroyDB() {
try {
Options options = new Options();
factory.destroy(new File("temp"), options);
} catch (IOException e) {
fail("Destroying temp-db failed");
}
}
}

View File

@ -1,187 +0,0 @@
package test.ethereum.jsontestsuite;
import org.ethereum.jsontestsuite.StateTestCase;
import org.ethereum.jsontestsuite.StateTestSuite;
import org.ethereum.jsontestsuite.TestCase;
import org.ethereum.jsontestsuite.TestRunner;
import org.ethereum.jsontestsuite.TestSuite;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
/**
* Test file specific for tests maintained in the GitHub repository
* by the Ethereum DEV team. <br/>
*
* @see <a href="https://github.com/ethereum/tests/">https://github.com/ethereum/tests/</a>
*/
@RunWith(Suite.class)
@SuiteClasses({
GitHubVMTest.class,
})
public class GitHubJSONTestSuite {
private static Logger logger = LoggerFactory.getLogger("TCK-Test");
protected static void runGitHubJsonVMTest(String json, String testName) throws ParseException {
Assume.assumeFalse("Online test is not available", json.equals(""));
JSONParser parser = new JSONParser();
JSONObject testSuiteObj = (JSONObject) parser.parse(json);
TestSuite testSuite = new TestSuite(testSuiteObj);
Iterator<TestCase> testIterator = testSuite.iterator();
for (TestCase testCase : testSuite.getAllTests()) {
String prefix = " ";
if (testName.equals(testCase.getName())) prefix = " => ";
logger.info(prefix + testCase.getName());
}
while (testIterator.hasNext()) {
TestCase testCase = testIterator.next();
if (testName.equals((testCase.getName()))) {
TestRunner runner = new TestRunner();
List<String> result = runner.runTestCase(testCase);
Assert.assertTrue(result.isEmpty());
return;
}
}
}
protected static void runGitHubJsonVMTest(String json) throws ParseException {
Set<String> excluded = new HashSet<>();
runGitHubJsonVMTest(json, excluded);
}
protected static void runGitHubJsonVMTest(String json, Set<String> excluded) throws ParseException {
Assume.assumeFalse("Online test is not available", json.equals(""));
JSONParser parser = new JSONParser();
JSONObject testSuiteObj = (JSONObject) parser.parse(json);
TestSuite testSuite = new TestSuite(testSuiteObj);
Iterator<TestCase> testIterator = testSuite.iterator();
for (TestCase testCase : testSuite.getAllTests()) {
String prefix = " ";
if (excluded.contains(testCase.getName())) prefix = "[X] ";
logger.info(prefix + testCase.getName());
}
while (testIterator.hasNext()) {
TestCase testCase = testIterator.next();
if (excluded.contains(testCase.getName()))
continue;
TestRunner runner = new TestRunner();
List<String> result = runner.runTestCase(testCase);
Assert.assertTrue(result.isEmpty());
}
}
protected static void runGitHubJsonStateTest(String json, String testName) throws ParseException {
Assume.assumeFalse("Online test is not available", json.equals(""));
JSONParser parser = new JSONParser();
JSONObject testSuiteObj = (JSONObject) parser.parse(json);
StateTestSuite testSuite = new StateTestSuite(testSuiteObj);
for (StateTestCase testCase : testSuite.getAllTests()) {
if (testCase.getName().equals(testName))
logger.info(" => " + testCase.getName());
else
logger.info(" " + testCase.getName());
}
StateTestCase testCase = testSuite.getTestCase(testName);
TestRunner runner = new TestRunner();
List<String> result = runner.runTestCase(testCase);
if (!result.isEmpty())
for (String single : result)
logger.info(single);
Assert.assertTrue(result.isEmpty());
}
protected static void runGitHubJsonStateTest(String json, Set<String> excluded) throws ParseException {
Assume.assumeFalse("Online test is not available", json.equals(""));
JSONParser parser = new JSONParser();
JSONObject testSuiteObj = (JSONObject) parser.parse(json);
StateTestSuite testSuite = new StateTestSuite(testSuiteObj);
Collection<StateTestCase> testCollection = testSuite.getAllTests();
for (StateTestCase testCase : testSuite.getAllTests()) {
String prefix = " ";
if (excluded.contains(testCase.getName())) prefix = "[X] ";
logger.info(prefix + testCase.getName());
}
for (StateTestCase testCase : testCollection) {
if (excluded.contains(testCase.getName())) continue;
TestRunner runner = new TestRunner();
List<String> result = runner.runTestCase(testCase);
if (!result.isEmpty())
for (String single : result)
logger.info(single);
Assert.assertTrue(result.isEmpty());
}
}
protected static void runGitHubJsonStateTest(String json) throws ParseException {
Assume.assumeFalse("Online test is not available", json.equals(""));
JSONParser parser = new JSONParser();
JSONObject testSuiteObj = (JSONObject) parser.parse(json);
StateTestSuite testSuite = new StateTestSuite(testSuiteObj);
Collection<StateTestCase> testCollection = testSuite.getAllTests();
for (StateTestCase testCase : testCollection) {
TestRunner runner = new TestRunner();
List<String> result = runner.runTestCase(testCase);
if (!result.isEmpty())
for (String single : result)
logger.info(single);
Assert.assertTrue(result.isEmpty());
logger.info(" *** Passed: " + testCase.getName());
}
}
}

View File

@ -1,125 +0,0 @@
package test.ethereum.jsontestsuite;
import org.ethereum.jsontestsuite.JSONReader;
import org.json.simple.parser.ParseException;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import java.util.HashSet;
import java.util.Set;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class GitHubStateTest {
//SHACOMMIT of tested commit, ethereum/tests.git
public String shacommit = "cfb120d1793dbb14404d9991f67cfb16bf573887";
@Ignore
@Test // this method is mostly for hands-on convenient testing
public void stSingleTest() throws ParseException {
String json = JSONReader.loadJSONFromCommit("StateTests/stSystemOperationsTest.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonStateTest(json, "CallRecursiveBombLog2");
}
@Test // this method is mostly for hands-on convenient testing
public void runWithExcludedTest() throws ParseException {
Set<String> excluded = new HashSet<>();
excluded.add("CallRipemd160_5");
excluded.add("CallSha256_5");
String json = JSONReader.loadJSONFromCommit("StateTests/stPreCompiledContracts.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonStateTest(json, excluded);
}
@Test
public void stExample() throws ParseException { // [V]
String json = JSONReader.loadJSONFromCommit("StateTests/stExample.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonStateTest(json);
}
@Test // todo: fix: excluded test
public void stInitCodeTest() throws ParseException { // [V]
Set<String> excluded = new HashSet<>();
String json = JSONReader.loadJSONFromCommit("StateTests/stInitCodeTest.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonStateTest(json, excluded);
}
@Test
public void stLogTests() throws ParseException { // [V]
String json = JSONReader.loadJSONFromCommit("StateTests/stLogTests.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonStateTest(json);
}
@Test
public void stPreCompiledContracts() throws ParseException {
Set<String> excluded = new HashSet<>();
excluded.add("CallRipemd160_5");
excluded.add("CallSha256_5");
String json = JSONReader.loadJSONFromCommit("StateTests/stPreCompiledContracts.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonStateTest(json, excluded);
}
@Test
public void stRecursiveCreate() throws ParseException { // [V]
String json = JSONReader.loadJSONFromCommit("StateTests/stRecursiveCreate.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonStateTest(json);
}
@Test
public void stRefundTest() throws ParseException { // [V]
Set<String> excluded = new HashSet<>();
excluded.add("refund_CallA");
excluded.add("refund_CallA2");
String json = JSONReader.loadJSONFromCommit("StateTests/stRefundTest.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonStateTest(json, excluded);
}
@Test
public void stSpecialTest() throws ParseException { // [V]
String json = JSONReader.loadJSONFromCommit("StateTests/stSpecialTest.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonStateTest(json);
}
@Test
public void stBlockHashTest() throws ParseException {
String json = JSONReader.loadJSONFromCommit("StateTests/stBlockHashTest.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonStateTest(json);
}
@Ignore //Input error (too large / badly formatted input)
@Test
public void stSystemOperationsTest() throws ParseException {
Set<String> excluded = new HashSet<>();
String json = JSONReader.loadJSONFromCommit("StateTests/stSystemOperationsTest.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonStateTest(json, excluded);
}
@Test // todo: fix: excluded test
public void stTransactionTest() throws ParseException {
Set<String> excluded = new HashSet<>();
//todo: it goes OOG, because no gasLimit is given. So it does not change the state.
excluded.add("HighGasLimit");
excluded.add("RefundOverflow");
excluded.add("UserTransactionZeroCostWithData");
excluded.add("UserTransactionGasLimitIsTooLowWhenZeroCost");
excluded.add("SuicidesAndInternlCallSuicides");
excluded.add("SuicidesMixingCoinbase");
excluded.add("CreateTransactionReverted");
String json = JSONReader.loadJSONFromCommit("StateTests/stTransactionTest.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonStateTest(json, excluded);
}
}

View File

@ -1,138 +0,0 @@
package test.ethereum.jsontestsuite;
import org.ethereum.jsontestsuite.JSONReader;
import org.json.simple.parser.ParseException;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.ethereum.jsontestsuite.JSONReader.getFileNamesForTreeSha;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class GitHubVMTest {
//SHACOMMIT of tested commit, ethereum/tests.git
public String shacommit = "eecee75336681dc8c0b7a2423997178eb2101f4e";
//public List<String> vmTestFiles = getFileNamesForTreeSha(shacommit);
@Test
public void runSingle() throws ParseException {
String json = JSONReader.loadJSONFromCommit("VMTests/vmEnvironmentalInfoTest.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonVMTest(json, "balance0");
}
@Test
@Ignore
public void testArithmeticFromGitHub() throws ParseException {
Set<String> excluded = new HashSet<>();
excluded.add("addmod1_overflowDiff");
excluded.add("addmod1_overflow3");
String json = JSONReader.loadJSONFromCommit("VMTests/vmArithmeticTest.json", shacommit);
//String json = JSONReader.getTestBlobForTreeSha(shacommit, "vmArithmeticTest.json");
GitHubJSONTestSuite.runGitHubJsonVMTest(json, excluded);
}
@Test // testing full suite
public void testBitwiseLogicOperationFromGitHub() throws ParseException {
Set<String> excluded = new HashSet<>();
String json = JSONReader.loadJSONFromCommit("VMTests/vmBitwiseLogicOperationTest.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonVMTest(json, excluded);
}
@Test // testing full suite
public void testBlockInfoFromGitHub() throws ParseException {
Set<String> excluded = new HashSet<>();
String json = JSONReader.loadJSONFromCommit("VMTests/vmBlockInfoTest.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonVMTest(json, excluded);
}
@Test // testing full suite
public void testEnvironmentalInfoFromGitHub() throws ParseException {
Set<String> excluded = new HashSet<>();
excluded.add("env1"); //Bug in test runner- this passes if VM logging is on "ALL"
String json = JSONReader.loadJSONFromCommit("VMTests/vmEnvironmentalInfoTest.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonVMTest(json, excluded);
}
@Test // testing full suite
public void testIOandFlowOperationsFromGitHub() throws ParseException {
Set<String> excluded = new HashSet<>();
String json = JSONReader.loadJSONFromCommit("VMTests/vmIOandFlowOperationsTest.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonVMTest(json, excluded);
}
@Ignore
@Test // testing random
public void testvmInputLimitsTest1FromGitHub() throws ParseException {
Set<String> excluded = new HashSet<>();
String json = JSONReader.loadJSONFromCommit("VMTests/vmInputLimitsTest1.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonVMTest(json, excluded);
}
@Test // testing full suite
public void testVMLogGitHub() throws ParseException {
Set<String> excluded = new HashSet<>();
String json = JSONReader.loadJSONFromCommit("VMTests/vmLogTest.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonVMTest(json, excluded);
}
@Test // testing full suite
public void testPushDupSwapFromGitHub() throws ParseException {
Set<String> excluded = new HashSet<>();
String json = JSONReader.loadJSONFromCommit("VMTests/vmPushDupSwapTest.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonVMTest(json, excluded);
}
@Test // testing full suite
public void testShaFromGitHub() throws ParseException {
Set<String> excluded = new HashSet<>();
String json = JSONReader.loadJSONFromCommit("VMTests/vmSha3Test.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonVMTest(json, excluded);
}
@Ignore
@Test // testing full suite
public void testvmSystemOperationsTestGitHub() throws ParseException {
Set<String> excluded = new HashSet<>();
String json = JSONReader.loadJSONFromCommit("VMTests/vmSystemOperationsTest.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonVMTest(json, excluded);
}
@Test // testing full suite
public void testVMGitHub() throws ParseException {
Set<String> excluded = new HashSet<>();
String json = JSONReader.loadJSONFromCommit("VMTests/vmtests.json", shacommit);
GitHubJSONTestSuite.runGitHubJsonVMTest(json, excluded);
}
@Test // testing full suite
public void testRandomVMGitHub() throws ParseException {
String sha = "60b921af8bf7bbe38565f8543e52a54e5f465ae8";
List<String> fileNames = getFileNamesForTreeSha(sha);
List<String> excludedFiles =
Arrays.asList(
"201501150842LARGE_DATA_IN_CALLCREATE_GOjson" //Badly named file
);
for (String fileName : fileNames) {
if (excludedFiles.contains(fileName)) continue;
System.out.println("Running: " + fileName);
String json = JSONReader.loadJSON("VMTests//RandomTests/" + fileName);
GitHubJSONTestSuite.runGitHubJsonVMTest(json);
}
}
}

View File

@ -1,59 +0,0 @@
package test.ethereum.mine;
import org.ethereum.core.Block;
import org.ethereum.mine.Miner;
import org.junit.Ignore;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
/**
* @author Roman Mandeleil
* @since 09.11.2014
*/
public class ForkGenTest {
@Test
@Ignore
public void mineOnBlock() {
byte[] blockRaw = Hex.decode("f90139f90134a077702830ce2f66cdbf82cabd600ddb760a68b73c93739bdd439309989b22f93ba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794907a0f5f767664ac77c8e431b99e74abc9288a40a0a2deb803ea8704997ae17efd0adf038df2833505da8776f095e32174dcb8e4aba056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b840000000000000000000000000000000000000000000002000000000004000000000000020000000000000000000000000000000000000000000000000000000008301f2363c8609184e72a000830e63bb80845461623980a05643fd40385c6520e3320109adc71917fdbbcdffe61f0b476ccb3b34111af194c0c0");
byte[] coinbase = Hex.decode("cd2a3d9f938e13cd947ec05abc7fe734df8dd826");
Block block = new Block(blockRaw);
Block newBlock = MinerThread.createBlock(block, coinbase);
newBlock.setStateRoot(Hex.decode("43bb67bea1931eca8f9e06f9cca66a9f9914cc3e3d4e9ceb2e08e58ab9f92bab"));
Miner miner = new Miner();
miner.mine(newBlock, newBlock.getDifficulty());
System.out.println(newBlock);
//f8f9f8f5a0a02852f3f5e7d06936bd5f39e7cc65a9f11e37656255f92c7eb32cb878a70213a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794cd2a3d9f938e13cd947ec05abc7fe734df8dd826a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421808301ef4e518609184e72a000830e1c69808601499c9bf5dd80a0000000000000000000000000000000000000000000000000000000000000f599c0c0
}
@Test
@Ignore
public void makeFork() {
MineSwarm swarm = new MineSwarm();
swarm.start();
while (swarm.started.get()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

View File

@ -1,96 +0,0 @@
package test.ethereum.mine;
import org.ethereum.core.Block;
import org.ethereum.net.peerdiscovery.RejectionLogger;
import org.spongycastle.util.encoders.Hex;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @author Roman Mandeleil
* @since 08.11.2014
*/
public class MineSwarm {
public AtomicBoolean started = new AtomicBoolean(false);
private ThreadFactory threadFactory;
private ThreadPoolExecutor executorPool;
private RejectedExecutionHandler rejectionHandler;
private AtomicBoolean found = new AtomicBoolean(false);
List<MinerThread> workers = new ArrayList<>();
private Queue<Block> blockAppearQueue = new ConcurrentLinkedQueue<>();
public void start() {
started.set(true);
// RejectedExecutionHandler implementation
rejectionHandler = new RejectionLogger();
// Get the ThreadFactory implementation to use
threadFactory = Executors.defaultThreadFactory();
MinerThread mt1 = new MinerThread("miner1", this, Hex.decode("2bd26d8f796719923ff13d295644f9b45db1f730"));
Thread miner1 = new Thread(mt1);
miner1.start();
workers.add(mt1);
MinerThread mt2 = new MinerThread("miner2", this, Hex.decode("f92c0f3e4825f09490ca264dc0cdacffeb566f06"));
Thread miner2 = new Thread(mt2);
miner2.start();
workers.add(mt2);
MinerThread mt3 = new MinerThread("miner3", this, Hex.decode("407d73d8a49eeb85d32cf465507dd71d507100c1"));
Thread miner3 = new Thread(mt3);
miner3.start();
workers.add(mt3);
while (!mt1.isDone() || !mt2.isDone() || !mt3.isDone()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
while (!blockAppearQueue.isEmpty()) {
System.out.println(
Hex.toHexString(blockAppearQueue.poll().getEncoded())
);
}
System.out.println("miner-1: TD: " + mt1.getChain().getTotalDifficulty() +
" chain.size: " + mt1.getChain().getSize());
System.out.println("miner-2: TD: " + mt2.getChain().getTotalDifficulty() +
" chain.size: " + mt2.getChain().getSize());
System.out.println("miner-3: TD: " + mt3.getChain().getTotalDifficulty() +
" chain.size: " + mt3.getChain().getSize());
}
public void announceBlock(Block block) {
for (MinerThread mt : workers) {
mt.onNewBlock(block);
}
}
public void addToQueue(Block block) {
synchronized (blockAppearQueue) {
blockAppearQueue.add(block);
}
}
}

View File

@ -1,177 +0,0 @@
package test.ethereum.mine;
import org.ethereum.core.Block;
import org.ethereum.core.BlockHeader;
import org.ethereum.core.Chain;
import org.ethereum.core.Genesis;
import org.ethereum.mine.Miner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import java.util.ArrayList;
import java.util.List;
/**
* @author Roman Mandeleil
* @since 22.05.2014
*/
public class MinerThread implements Runnable {
private final static Logger logger = LoggerFactory.getLogger("miner");
private final byte[] coinbase;
private MineSwarm mineSwarm;
private String name;
private boolean done = false;
private Miner miner = new Miner();
private Chain mainChain = new Chain();
private List<Chain> altChains = new ArrayList<>();
private Block tmpBlock = null;
private List<Block> uncles = new ArrayList<>();
private Block announcedBlock = null;
public MinerThread(String name, MineSwarm mineSwarm, byte[] coinbase) {
this.name = name;
this.mineSwarm = mineSwarm;
this.coinbase = coinbase;
Block genesis = Genesis.getInstance();
mainChain.add(genesis);
}
@Override
public void run() {
logger.debug("{} start", name);
doRun();
logger.debug("{} end", name);
}
public void onNewBlock(Block foundBlock) {
if (mainChain.getLast().isEqual(foundBlock)) {
// That is our announcement, do nothing.
return;
}
logger.info("{}: Ohh.. I heard the block was found already: {}: {} ^ {}", name,
foundBlock.getNumber(), Hex.toHexString(foundBlock.getHash()).substring(0, 6),
Hex.toHexString(foundBlock.getParentHash()).substring(0, 6));
if (mainChain.getLast().isParentOf(foundBlock)) {
logger.info("{}: adding by announce to main chain. hash:{} ", name,
Hex.toHexString(foundBlock.getHash()).substring(0, 6));
// add it as main block
announcedBlock = foundBlock;
miner.stop();
} else {
if (mainChain.isParentOnTheChain(foundBlock)) {
logger.info("{} found an uncle. on index: {}", name, foundBlock.getNumber());
// add it as a future uncle
uncles.add(foundBlock);
} else {
logger.info("{}: nothing to do, maybe alt chain: {}: {} ^ {}", name,
foundBlock.getNumber(), Hex.toHexString(foundBlock.getHash()).substring(0, 6),
Hex.toHexString(foundBlock.getParentHash()).substring(0, 6));
}
}
}
public void announceBlock(Block block) {
mineSwarm.announceBlock(block);
}
private void doRun() {
Block genesis = mainChain.getLast();
tmpBlock = createBlock(genesis, coinbase);
while (!done) {
this.announcedBlock = null;
logger.info("{}: before mining: chain.size: [{}], chain.TD: [{}]", name,
mainChain.getSize(), mainChain.getTotalDifficulty());
boolean found = miner.mine(tmpBlock, tmpBlock.getDifficulty());
logger.info("{}: finished mining, found: [{}]", name, found);
if (!found && announcedBlock != null) {
mainChain.add(announcedBlock);
tmpBlock = createBlock(announcedBlock, coinbase);
}
if (found) {
mineSwarm.addToQueue(tmpBlock);
logger.info("{}: mined block: {} --> {} ^ {}", name, tmpBlock.getNumber(),
Hex.toHexString(tmpBlock.getHash()).substring(0, 6),
Hex.toHexString(tmpBlock.getParentHash()).substring(0, 6));
if (announcedBlock != null)
logger.info("{}: forked on: {}", name, tmpBlock.getNumber());
logger.info("{}: adding to main chain. hash:{} ", name,
Hex.toHexString(tmpBlock.getHash()).substring(0, 6));
mainChain.add(tmpBlock);
sleep();
announceBlock(tmpBlock);
tmpBlock = createBlock(tmpBlock, coinbase);
}
if (!uncles.isEmpty()) {
for (Block uncle : uncles) {
BlockHeader uncleHeader = uncle.getHeader();
tmpBlock.addUncle(uncleHeader);
logger.info("{} adding {} uncles to block: {}", name, uncles.size(), tmpBlock.getNumber());
}
uncles.clear();
}
if (mainChain.getSize() == 100) done = true;
}
}
public static Block createBlock(Block lastBlock, byte[] coinbase) {
long timeDiff = System.currentTimeMillis() - lastBlock.getTimestamp();
byte[] difficulty = lastBlock.getDifficulty();
// if (timeDiff < 5000){
// System.out.println("increase");
// BigInteger diff = (new BigInteger(1, lastBlock.getDifficulty()).add(new BigInteger("FFF", 16)));
// difficulty = diff.toByteArray();
// }
Block newBlock = new Block(lastBlock.getHash(), lastBlock.getUnclesHash(), coinbase, lastBlock.getLogBloom(),
difficulty, lastBlock.getNumber() + 1,
lastBlock.getGasLimit(), lastBlock.getGasUsed(), System.currentTimeMillis() / 1000,
null, null, null, null);
return newBlock;
}
public boolean isDone() {
return done;
}
public Chain getChain() {
return mainChain;
}
private void sleep() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,106 +0,0 @@
package test.ethereum.net;
import org.ethereum.net.message.ReasonCode;
import org.ethereum.net.p2p.DisconnectMessage;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
import static org.junit.Assert.*;
public class DisconnectMessageTest {
/* DISCONNECT_MESSAGE */
@Test /* DisconnectMessage 1 - Requested */
public void test_1() {
String disconnectMessageRaw = "C20100";
byte[] payload = Hex.decode(disconnectMessageRaw);
DisconnectMessage disconnectMessage = new DisconnectMessage(payload);
System.out.println(disconnectMessage);
assertEquals(disconnectMessage.getReason(), ReasonCode.REQUESTED);
}
@Test /* DisconnectMessage 2 - TCP Error */
public void test_2() {
String disconnectMessageRaw = "C20101";
byte[] payload = Hex.decode(disconnectMessageRaw);
DisconnectMessage disconnectMessage = new DisconnectMessage(payload);
System.out.println(disconnectMessage);
assertEquals(disconnectMessage.getReason(), ReasonCode.TCP_ERROR);
}
@Test /* DisconnectMessage 2 - from constructor */
public void test_3() {
DisconnectMessage disconnectMessage = new DisconnectMessage(ReasonCode.INCOMPATIBLE_NETWORK);
System.out.println(disconnectMessage);
String expected = "c20107";
assertEquals(expected, Hex.toHexString(disconnectMessage.getEncoded()));
assertEquals(ReasonCode.INCOMPATIBLE_NETWORK, disconnectMessage.getReason());
}
@Test //handling boundary-high
public void test_4() {
String disconnectMessageRaw = "C28080";
byte[] payload = Hex.decode(disconnectMessageRaw);
DisconnectMessage disconnectMessage = new DisconnectMessage(payload);
System.out.println(disconnectMessage);
assertEquals(disconnectMessage.getReason(), ReasonCode.REQUESTED); //high numbers are zeroed
}
@Test //handling boundary-low
public void test_5() {
String disconnectMessageRaw = "C20000";
byte[] payload = Hex.decode(disconnectMessageRaw);
DisconnectMessage disconnectMessage = new DisconnectMessage(payload);
System.out.println(disconnectMessage);
assertEquals(disconnectMessage.getReason(), ReasonCode.REQUESTED);
}
@Test //handling boundary-low minus 1 (error)
public void test_6() {
String disconnectMessageRaw = "C19999";
byte[] payload = Hex.decode(disconnectMessageRaw);
try {
DisconnectMessage disconnectMessage = new DisconnectMessage(payload);
disconnectMessage.toString(); //throws exception
assertTrue("Valid raw encoding for disconnectMessage", false);
} catch (RuntimeException e) {
assertTrue("Invalid raw encoding for disconnectMessage", true);
}
}
@Test //handling boundary-high plus 1 (error)
public void test_7() {
String disconnectMessageRaw = "C28081";
byte[] payload = Hex.decode(disconnectMessageRaw);
try {
DisconnectMessage disconnectMessage = new DisconnectMessage(payload);
disconnectMessage.toString(); //throws exception
assertTrue("Valid raw encoding for disconnectMessage", false);
} catch (RuntimeException e) {
assertTrue("Invalid raw encoding for disconnectMessage", true);
}
}
}

View File

@ -1,47 +0,0 @@
package test.ethereum.net;
import org.ethereum.net.eth.BlockHashesMessage;
import org.ethereum.net.eth.EthMessageCodes;
import org.ethereum.net.eth.GetBlockHashesMessage;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
import static org.junit.Assert.assertEquals;
public class GetBlockHashesMessageTest {
/* BLOCK_HASHES_MESSAGE */
@Test /* BlockHashesMessage 1 from network */
public void test_1() {
String blockHashesMessageRaw = "e513a05ad1c9caeade4cdf5798e796dc87939231d9c76c20a6a33fea6dab8e9d6dd009820100";
byte[] payload = Hex.decode(blockHashesMessageRaw);
GetBlockHashesMessage getBlockHashesMessage = new GetBlockHashesMessage(payload);
System.out.println(getBlockHashesMessage);
assertEquals(EthMessageCodes.GET_BLOCK_HASHES, getBlockHashesMessage.getCommand());
assertEquals("5ad1c9caeade4cdf5798e796dc87939231d9c76c20a6a33fea6dab8e9d6dd009", Hex.toHexString(getBlockHashesMessage.getBestHash()));
assertEquals(256, getBlockHashesMessage.getMaxBlocks());
assertEquals(BlockHashesMessage.class, getBlockHashesMessage.getAnswerMessage());
}
@Test /* GetBlockHashesMessage 2 from new */
public void test_2() {
byte[] bestHash = Hex.decode("455408387e6c5b029b0d51f7d617a4d1dc4895fa6eda09455cc2ee62c08d907e");
GetBlockHashesMessage getBlockHashesMessage = new GetBlockHashesMessage(bestHash, 128);
System.out.println(getBlockHashesMessage);
String expected = "e403a0455408387e6c5b029b0d51f7d617a4d1dc4895fa6eda09455cc2ee62c08d907e8180";
assertEquals(expected, Hex.toHexString(getBlockHashesMessage.getEncoded()));
assertEquals(EthMessageCodes.GET_BLOCK_HASHES, getBlockHashesMessage.getCommand());
assertEquals(Hex.toHexString(bestHash), Hex.toHexString(getBlockHashesMessage.getBestHash()));
assertEquals(128, getBlockHashesMessage.getMaxBlocks());
assertEquals(BlockHashesMessage.class, getBlockHashesMessage.getAnswerMessage());
}
}

View File

@ -1,59 +0,0 @@
package test.ethereum.net;
import org.ethereum.net.eth.BlocksMessage;
import org.ethereum.net.eth.EthMessageCodes;
import org.ethereum.net.eth.GetBlocksMessage;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertEquals;
public class GetBlocksMessageTest {
/* GET_BLOCKS */
@Test /* GetBlocks message parsing */
public void test_1() {
String getBlocksMessageRaw = "f8a615a0497dcbd12fa99ced7b27cda6611f64eb13ab50e20260eec5ee6b7190e7206d54a00959bdfba5e54fcc9370e86b7996fbe32a277bab65c31a0102226f83c4d3e0f2a001a333c156485880776e929e84c26c9778c1e9b4dcb5cd3bff8ad0aeff385df0a0690e13595c9e8e4fa9a621dfed6ad828a6e8e591479af6897c979a83daf73084a0b20f253d2b62609e932c13f3bca59a22913ea5b1e532d8a707976997461ec143";
byte[] payload = Hex.decode(getBlocksMessageRaw);
GetBlocksMessage getBlocksMessage = new GetBlocksMessage(payload);
System.out.println(getBlocksMessage);
assertEquals(EthMessageCodes.GET_BLOCKS, getBlocksMessage.getCommand());
assertEquals(5, getBlocksMessage.getBlockHashes().size());
String hash1 = "497dcbd12fa99ced7b27cda6611f64eb13ab50e20260eec5ee6b7190e7206d54";
String hash4 = "b20f253d2b62609e932c13f3bca59a22913ea5b1e532d8a707976997461ec143";
assertEquals(hash1, Hex.toHexString(getBlocksMessage.getBlockHashes().get(0)));
assertEquals(hash4, Hex.toHexString(getBlocksMessage.getBlockHashes().get(4)));
assertEquals(BlocksMessage.class, getBlocksMessage.getAnswerMessage());
}
@Test /* GetBlocks from new */
public void test_2() {
List<byte[]> hashList = Arrays.asList(
Hex.decode("497dcbd12fa99ced7b27cda6611f64eb13ab50e20260eec5ee6b7190e7206d54"),
Hex.decode("0959bdfba5e54fcc9370e86b7996fbe32a277bab65c31a0102226f83c4d3e0f2"),
Hex.decode("01a333c156485880776e929e84c26c9778c1e9b4dcb5cd3bff8ad0aeff385df0"),
Hex.decode("690e13595c9e8e4fa9a621dfed6ad828a6e8e591479af6897c979a83daf73084"),
Hex.decode("b20f253d2b62609e932c13f3bca59a22913ea5b1e532d8a707976997461ec143"));
GetBlocksMessage getBlocksMessage = new GetBlocksMessage(hashList);
System.out.println(getBlocksMessage);
String expected = "f8a605a0497dcbd12fa99ced7b27cda6611f64eb13ab50e20260eec5ee6b7190e7206d54a00959bdfba5e54fcc9370e86b7996fbe32a277bab65c31a0102226f83c4d3e0f2a001a333c156485880776e929e84c26c9778c1e9b4dcb5cd3bff8ad0aeff385df0a0690e13595c9e8e4fa9a621dfed6ad828a6e8e591479af6897c979a83daf73084a0b20f253d2b62609e932c13f3bca59a22913ea5b1e532d8a707976997461ec143";
assertEquals(expected, Hex.toHexString(getBlocksMessage.getEncoded()));
assertEquals(EthMessageCodes.GET_BLOCKS, getBlocksMessage.getCommand());
assertEquals(5, getBlocksMessage.getBlockHashes().size());
assertEquals(BlocksMessage.class, getBlocksMessage.getAnswerMessage());
}
}

View File

@ -1,35 +0,0 @@
package test.ethereum.net;
import org.ethereum.net.p2p.GetPeersMessage;
import org.ethereum.net.p2p.P2pMessageCodes;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
import static org.junit.Assert.assertEquals;
public class GetPeersMessageTest {
/* GETPEERS_MESSAGE */
@Test
public void testGetPeers() {
//Init
GetPeersMessage getPeersMessage = new GetPeersMessage();
//toString
assertEquals("[GET_PEERS]", getPeersMessage.toString());
//getEncoded
assertEquals("C104", Hex.toHexString(getPeersMessage.getEncoded()).toUpperCase());
//getAnswerMessage
assertEquals(null, getPeersMessage.getAnswerMessage());
//getCommand
assertEquals(P2pMessageCodes.GET_PEERS, getPeersMessage.getCommand());
}
}

View File

@ -1,95 +0,0 @@
package test.ethereum.net;
import org.ethereum.net.client.Capability;
import org.ethereum.net.eth.EthHandler;
import org.ethereum.net.p2p.HelloMessage;
import org.ethereum.net.p2p.P2pHandler;
import org.ethereum.net.p2p.P2pMessageCodes;
import org.ethereum.net.shh.ShhHandler;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertEquals;
public class HelloMessageTest {
/* HELLO_MESSAGE */
private static final Logger logger = LoggerFactory.getLogger("test");
//Parsing from raw bytes
@Test
public void test1() {
String helloMessageRaw = "f87a8002a5457468657265756d282b2b292f76302e372e392f52656c656173652f4c696e75782f672b2bccc58365746827c583736868018203e0b8401fbf1e41f08078918c9f7b6734594ee56d7f538614f602c71194db0a1af5a77f9b86eb14669fe7a8a46a2dd1b7d070b94e463f4ecd5b337c8b4d31bbf8dd5646";
byte[] payload = Hex.decode(helloMessageRaw);
HelloMessage helloMessage = new HelloMessage(payload);
logger.info(helloMessage.toString());
assertEquals(P2pMessageCodes.HELLO, helloMessage.getCommand());
assertEquals(2, helloMessage.getP2PVersion());
assertEquals("Ethereum(++)/v0.7.9/Release/Linux/g++", helloMessage.getClientId());
assertEquals(2, helloMessage.getCapabilities().size());
assertEquals(992, helloMessage.getListenPort());
assertEquals(
"1fbf1e41f08078918c9f7b6734594ee56d7f538614f602c71194db0a1af5a77f9b86eb14669fe7a8a46a2dd1b7d070b94e463f4ecd5b337c8b4d31bbf8dd5646",
helloMessage.getPeerId());
}
//Instantiate from constructor
@Test
public void test2() {
//Init
byte version = 2;
String clientStr = "Ethereum(++)/v0.7.9/Release/Linux/g++";
List<Capability> capabilities = Arrays.asList(
new Capability(Capability.ETH, EthHandler.VERSION),
new Capability(Capability.SHH, ShhHandler.VERSION),
new Capability(Capability.P2P, P2pHandler.VERSION));
int listenPort = 992;
String peerId = "1fbf1e41f08078918c9f7b6734594ee56d7f538614f602c71194db0a1af5a";
HelloMessage helloMessage = new HelloMessage(version, clientStr, capabilities, listenPort, peerId);
logger.info(helloMessage.toString());
assertEquals(P2pMessageCodes.HELLO, helloMessage.getCommand());
assertEquals(version, helloMessage.getP2PVersion());
assertEquals(clientStr, helloMessage.getClientId());
assertEquals(3, helloMessage.getCapabilities().size());
assertEquals(listenPort, helloMessage.getListenPort());
assertEquals(peerId, helloMessage.getPeerId());
//TODO tostring?
}
//Fail test
@Test
public void test3() {
//Init
byte version = -1; //invalid version
String clientStr = ""; //null id
List<Capability> capabilities = Arrays.asList(
new Capability(null, (byte) 0),
new Capability(null, (byte) 0),
null, //null here causes NullPointerException when using toString
new Capability(null, (byte) 0)); //encoding null capabilities
int listenPort = 99999; //invalid port
String peerId = ""; //null id
HelloMessage helloMessage = new HelloMessage(version, clientStr, capabilities, listenPort, peerId);
assertEquals(P2pMessageCodes.HELLO, helloMessage.getCommand());
assertEquals(version, helloMessage.getP2PVersion());
assertEquals(clientStr, helloMessage.getClientId());
assertEquals(4, helloMessage.getCapabilities().size());
assertEquals(listenPort, helloMessage.getListenPort());
assertEquals(peerId, helloMessage.getPeerId());
}
}

View File

@ -1,44 +0,0 @@
package test.ethereum.net;
import org.ethereum.core.Block;
import org.ethereum.net.eth.NewBlockMessage;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
public class NewBlockMessageTest {
private static final Logger logger = LoggerFactory.getLogger("test");
/* NEW_BLOCK */
@Test
public void test_1() {
String newBlockRaw = "f9014517f9013Bf90136a0d8faffbc4c4213d35db9007de41cece45d95db7fd6c0f129e158baa888c48eefa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794baedba0480e1b882b606cd302d8c4f5701cabac7a0c7d4565fb7b3d98e54a0dec8b76f8c001a784a5689954ce0aedcc1bbe8d13095a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b8400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083063477825fc88609184e72a0008301e8488084543ffee680a00de0b9d4a0f0c23546d31f1f70db00d25cf6a7af79365b4e058e4a6a3b69527bc0c0850177ddbebe";
byte[] payload = Hex.decode(newBlockRaw);
NewBlockMessage newBlockMessage = new NewBlockMessage(payload);
logger.info(newBlockMessage.toString());
}
@Test
public void test_2() {
Block block = new Block(
Hex.decode("f90277f8cfa0887ef3904d3c464cbb3ce2a7e2ce02c57b1a38caaa5013ad1202ead0fc1077baa0a962ba850109a5112e7bd3109db477014057b478772825173cc3da54cfc3264e94407d73d8a49eeb85d32cf465507dd71d507100c180a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000380830f42408086014997893f1080a000000000000000000000000000000000000000000000000000000000000018e9c0f901a2f8cfa0955f36d073ccb026b78ab3424c15cf966a7563aa270413859f78702b9e8e22cba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942bd26d8f796719923ff13d295644f9b45db1f73080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000180830f4240808601499789326680a00000000000000000000000000000000000000000000000000000000000010da5f8cfa0717e058643634a0f80b9cf33da423d304dabaa826c586f50a783ba6c70cfd60da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794f92c0f3e4825f09490ca264dc0cdacffeb566f0680a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000280830f424080860149978936fe80a0000000000000000000000000000000000000000000000000000000000001d01f"));
byte[] diff = new byte[]{0};
NewBlockMessage nbm = new NewBlockMessage(block, diff);
System.out.println(nbm.toString());
}
}

View File

@ -1,60 +0,0 @@
package test.ethereum.net;
import org.ethereum.net.client.Capability;
import org.ethereum.net.p2p.Peer;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
public class PeerTest {
/* PEER */
@Test
public void testPeer() {
//Init
InetAddress address = InetAddress.getLoopbackAddress();
List<Capability> capabilities = new ArrayList<>();
int port = 1010;
String peerId = "1010";
Peer peerCopy = new Peer(address, port, peerId);
//Peer
Peer peer = new Peer(address, port, peerId);
//getAddress
assertEquals("127.0.0.1", peer.getAddress().getHostAddress());
//getPort
assertEquals(port, peer.getPort());
//getPeerId
assertEquals(peerId, peer.getPeerId());
//getCapabilities
assertEquals(capabilities, peer.getCapabilities());
//getEncoded
assertEquals("CC847F0000018203F2821010C0", Hex.toHexString(peer.getEncoded()).toUpperCase());
//toString
assertEquals("[ip=" + address.getHostAddress() + " port=" + Integer.toString(port) + " peerId=" + peerId + "]", peer.toString());
//equals
assertEquals(true, peer.equals(peerCopy));
assertEquals(false, peer.equals(null));
//hashCode
assertEquals(-1, peer.hashCode());
}
}

View File

@ -1,118 +0,0 @@
package test.ethereum.net;
import org.ethereum.net.client.Capability;
import org.ethereum.net.p2p.GetPeersMessage;
import org.ethereum.net.p2p.P2pMessageCodes;
import org.ethereum.net.p2p.Peer;
import org.ethereum.net.p2p.PeersMessage;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import static org.junit.Assert.assertEquals;
public class PeersMessageTest {
/* GET_PEERS */
private static final Logger logger = LoggerFactory.getLogger("test");
@Test /* GetPeersMessage */
public void testGetPeers() {
GetPeersMessage getPeersMessage = new GetPeersMessage();
logger.info(getPeersMessage.toString());
assertEquals(P2pMessageCodes.GET_PEERS, getPeersMessage.getCommand());
}
/* PEERS */
@Test /* PeersMessage 1 from RLP */
public void testPeers_1() {
String peersMessageRaw = "f84b05f848846894d84870b84036659c3656c488437cceb11abeb9b9fc69b8055144a7e7db3584d03e606083f90e17a1d3021d674579407cdaaafdfeef485872ab719db9f2b6283f498bb90a71";
byte[] payload = Hex.decode(peersMessageRaw);
PeersMessage peersMessage = new PeersMessage(payload);
logger.info(peersMessage.toString());
assertEquals(1, peersMessage.getPeers().size());
Iterator<Peer> it = peersMessage.getPeers().iterator();
Peer peer = it.next();
assertEquals(P2pMessageCodes.PEERS, peersMessage.getCommand());
assertEquals("/104.148.216.72", peer.getAddress().toString());
assertEquals(112, peer.getPort());
assertEquals("36659c3656c488437cceb11abeb9b9fc69b8055144a7e7db3584d03e606083f90e17a1d3021d674579407cdaaafdfeef485872ab719db9f2b6283f498bb90a71",
peer.getPeerId());
}
@Test /* PeersMessage 1 from constructor */
public void testPeers_2() {
//Init
InetAddress address = InetAddress.getLoopbackAddress();
List<Capability> capabilities = new ArrayList<>();
int port = 112;
String peerId = "36659c3656c488437cceb11abeb9b9fc69b8055144a7e7db3584d03e606083f90e" +
"17a1d3021d674579407cdaaafdfeef485872ab719db9f2b6283f498bb90a71";
Set<Peer> peers = new HashSet<>();
peers.add(new Peer(address, port, peerId));
PeersMessage peersMessage = new PeersMessage(peers);
logger.info(peersMessage.toString());
assertEquals(1, peersMessage.getPeers().size());
Iterator<Peer> it = peersMessage.getPeers().iterator();
Peer peer = it.next();
assertEquals(P2pMessageCodes.PEERS, peersMessage.getCommand());
assertEquals("127.0.0.1", peer.getAddress().getHostAddress());
assertEquals(112, peer.getPort());
assertEquals("36659c3656c488437cceb11abeb9b9fc69b8055144a7e7db3584d03e6" +
"06083f90e17a1d3021d674579407cdaaafdfeef485872ab719db9f2b6283f498bb90a71", peer.getPeerId());
}
@Test /* failing test */
public void testPeers_3() {
//Init
InetAddress address = InetAddress.getLoopbackAddress();
List<Capability> capabilities = Arrays.asList(
new Capability(null, (byte) 0),
null //null here can cause NullPointerException when using toString
); //encoding null capabilities
int port = -1; //invalid port
String peerId = ""; //invalid peerid
Set<Peer> peers = new HashSet<>();
peers.add(new Peer(address, port, peerId));
PeersMessage peersMessage = new PeersMessage(peers);
logger.info(peersMessage.toString());
assertEquals(1, peersMessage.getPeers().size());
Iterator<Peer> it = peersMessage.getPeers().iterator();
Peer peer = it.next();
assertEquals(P2pMessageCodes.PEERS, peersMessage.getCommand());
assertEquals("127.0.0.1", peer.getAddress().getHostAddress());
assertEquals(-1, peer.getPort());
assertEquals("", peer.getPeerId());
}
}

View File

@ -1,36 +0,0 @@
package test.ethereum.net;
import org.ethereum.net.p2p.P2pMessageCodes;
import org.ethereum.net.p2p.PingMessage;
import org.ethereum.net.p2p.PongMessage;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class PingPongMessageTest {
/* PING_MESSAGE & PONG_MESSAGE */
@Test /* PingMessage */
public void testPing() {
PingMessage pingMessage = new PingMessage();
System.out.println(pingMessage);
assertEquals(PongMessage.class, pingMessage.getAnswerMessage());
assertEquals(P2pMessageCodes.PING, pingMessage.getCommand());
}
@Test /* PongMessage */
public void testPong() {
PongMessage pongMessage = new PongMessage();
System.out.println(pongMessage);
assertEquals(P2pMessageCodes.PONG, pongMessage.getCommand());
assertEquals(null, pongMessage.getAnswerMessage());
}
}

View File

@ -1,246 +0,0 @@
package test.ethereum.net;
import org.ethereum.crypto.ECKey;
import org.ethereum.net.rlpx.*;
import org.ethereum.util.RLP;
import org.ethereum.util.RLPList;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;
import static org.ethereum.crypto.HashUtil.sha3;
import static org.ethereum.util.ByteUtil.merge;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class RLPXTest {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger("test");
@Test // ping test
public void test1() {
String ip = "85.65.19.231";
int port = 30303;
ECKey key = ECKey.fromPrivate(BigInteger.TEN);
Message ping = PingMessage.create(ip, port, key);
logger.info("{}", ping);
byte[] wire = ping.getPacket();
PingMessage ping2 = (PingMessage) Message.decode(wire);
logger.info("{}", ping2);
assertEquals(ping.toString(), ping2.toString());
String key2 = ping2.getKey().toString();
assertEquals(key.toString(), key2.toString());
}
@Ignore
@Test // pong test
public void test2() {
byte[] token = sha3("+++".getBytes(Charset.forName("UTF-8")));
ECKey key = ECKey.fromPrivate(BigInteger.TEN);
Message pong = PongMessage.create(token, key);
logger.info("{}", pong);
byte[] wire = pong.getPacket();
PongMessage pong2 = (PongMessage) Message.decode(wire);
logger.info("{}", pong);
assertEquals(pong.toString(), pong2.toString());
String key2 = pong2.getKey().toString();
assertEquals(key.toString(), key2.toString());
}
@Test // neighbors message
public void test3() {
String ip = "85.65.19.231";
int port = 30303;
byte[] part1 = sha3("007".getBytes(Charset.forName("UTF-8")));
byte[] part2 = sha3("007".getBytes(Charset.forName("UTF-8")));
byte[] id = merge(part1, part2);
Node node = new Node(id, ip, port);
List<Node> nodes = Arrays.asList(node);
ECKey key = ECKey.fromPrivate(BigInteger.TEN);
Message neighbors = NeighborsMessage.create(nodes, key);
logger.info("{}", neighbors);
byte[] wire = neighbors.getPacket();
NeighborsMessage neighbors2 = (NeighborsMessage) Message.decode(wire);
logger.info("{}", neighbors2);
assertEquals(neighbors.toString(), neighbors2.toString());
String key2 = neighbors2.getKey().toString();
assertEquals(key.toString(), key2.toString());
}
@Test // find node message
public void test4() {
byte[] id = sha3("+++".getBytes(Charset.forName("UTF-8")));
ECKey key = ECKey.fromPrivate(BigInteger.TEN);
Message findNode = FindNodeMessage.create(id, key);
logger.info("{}", findNode);
byte[] wire = findNode.getPacket();
FindNodeMessage findNode2 = (FindNodeMessage) Message.decode(wire);
logger.info("{}", findNode2);
assertEquals(findNode.toString(), findNode2.toString());
String key2 = findNode2.getKey().toString();
assertEquals(key.toString(), key2.toString());
}
@Test(expected = Error.class)// failure on MDC
public void test5() {
byte[] id = sha3("+++".getBytes(Charset.forName("UTF-8")));
ECKey key = ECKey.fromPrivate(BigInteger.TEN);
Message findNode = FindNodeMessage.create(id, key);
logger.info("{}", findNode);
byte[] wire = findNode.getPacket();
wire[64] = 0;
FindNodeMessage findNode2 = (FindNodeMessage) Message.decode(wire);
logger.info("{}", findNode2);
assertEquals(findNode.toString(), findNode2.toString());
}
@Test
public void test6() {
byte[] id_1 = sha3("+++".getBytes(Charset.forName("UTF-8")));
String host_1 = "85.65.19.231";
int port_1 = 30303;
Node node_1 = new Node(id_1, host_1 , port_1);
Node node_2 = new Node(node_1.getRLP());
byte[] id_2 = node_2.getId();
String host_2 = node_2.getHost();
int port_2 = node_2.getPort();
assertEquals(Hex.toHexString(id_1), Hex.toHexString(id_2));
assertEquals(host_1, host_2);
assertTrue(port_1 == port_2);
}
@Test // Neighbors parse data
public void test7() {
byte[] wire =
Hex.decode("d5106e888eeca1e0b4a93bf17c325f912b43ca4176a000966619aa6a96ac9d5a60e66c73ed5629c13d4d0c806a3127379541e8d90d7fcb52c33c5e36557ad92dfed9619fcd3b92e42683aed89bd3c6eef6b59bd0237c36d83ebb0075a59903f50104f90200f901f8f8528c38352e36352e31392e32333182f310b840aeb2dd107edd996adf1bbf835fb3f9a11aabb7ed3dfef84c7a3c8767482bff522906a11e8cddee969153bf5944e64e37943db509bb4cc714c217f20483802ec0f8528c38352e36352e31392e32333182e5b4b840b70cdf8f23024a65afbf12110ca06fa5c37bd9fe4f6234a0120cdaaf16e8bb96d090d0164c316aaa18158d346e9b0a29ad9bfa0404ab4ee9906adfbacb01c21bf8528c38352e36352e31392e32333182df38b840ed8e01b5f5468f32de23a7524af1b35605ffd7cdb79af4eacd522c94f8ed849bb81dfed4992c179caeef0952ecad2d868503164a434c300356b369a33c159289f8528c38352e36352e31392e32333182df38b840136996f11c2c80f231987fc4f0cbd061cb021c63afaf5dd879e7c851a57be8d023af14bc201be81588ecab7971693b3f689a4854df74ad2e2334e88ae76aa122f8528c38352e36352e31392e32333182f303b840742eac32e1e2343b89c03a20fc051854ea6a3ff28ca918d1994fe1e32d6d77ab63352131db3ed0e7d6cc057d859c114b102f49052daee3d1c5f5fdaab972e655f8528c38352e36352e31392e32333182f310b8407d9e1f9ceb66fc21787b830554d604f933be203be9366710fb33355975e874a72b87837cf28b1b9ae171826b64e3c5d178326cbf71f89b3dec614816a1a40ce38454f6b578");
NeighborsMessage msg1 = (NeighborsMessage) NeighborsMessage.decode(wire);
ECKey key = ECKey.fromPrivate(BigInteger.TEN);
NeighborsMessage msg2 = (NeighborsMessage) NeighborsMessage.create(msg1.getNodes(), key);
NeighborsMessage msg3 = (NeighborsMessage) NeighborsMessage.decode(msg2.getPacket());
for (int i = 0; i < msg1.getNodes().size(); ++i) {
Node node_1 = msg1.getNodes().get(i);
Node node_3 = msg3.getNodes().get(i);
assertEquals(node_1.toString(), node_3.toString());
}
System.out.println(msg1);
}
@Test // FindNodeMessage parse data
public void test8() {
byte[] wire =
Hex.decode("3770d98825a42cb69edf70ffdf8d6d2b28a8c5499a7e3350e4a42c94652339cac3f8e9c3b5a181c8dd13e491ad9229f6a8bd018d786e1fb9e5264f43bbd6ce93af9bc85b468dee651bcd518561f83cb166da7aef7e506057dc2fbb2ea582bcc00003f847b84083fba54f6bb80ce31f6d5d1ec0a9a2e4685bc185115b01da6dcb70cd13116a6bd08b86ffe60b7d7ea56c6498848e3741113f8e70b9f0d12dbfe895680d03fd658454f6e772");
FindNodeMessage msg1 = (FindNodeMessage) FindNodeMessage.decode(wire);
ECKey key = ECKey.fromPrivate(BigInteger.TEN);
FindNodeMessage msg2 = FindNodeMessage.create(msg1.getTarget(), key);
FindNodeMessage msg3 = (FindNodeMessage) FindNodeMessage.decode(msg2.getPacket());
Assert.assertEquals(Hex.toHexString(msg1.getTarget()), Hex.toHexString(msg3.getTarget()));
}
@Test // Ping parse data
public void test9() {
// wire: 4c62e1b75f4003ef77032006a142bbf31772936a1e5098566b28a04a5c71c73f1f2c9f539a85458c50a554de12da9d7e69fb2507f7c0788885508d385bbe7a9538fa675712aa1eaad29902bb46eee4531d00a10fd81179e4151929f60fec4dc50001ce87302e302e302e30808454f8483c
// PingMessage: {mdc=4c62e1b75f4003ef77032006a142bbf31772936a1e5098566b28a04a5c71c73f, signature=1f2c9f539a85458c50a554de12da9d7e69fb2507f7c0788885508d385bbe7a9538fa675712aa1eaad29902bb46eee4531d00a10fd81179e4151929f60fec4dc500, type=01, data=ce87302e302e302e30808454f8483c}
byte[] wire =
Hex.decode("4c62e1b75f4003ef77032006a142bbf31772936a1e5098566b28a04a5c71c73f1f2c9f539a85458c50a554de12da9d7e69fb2507f7c0788885508d385bbe7a9538fa675712aa1eaad29902bb46eee4531d00a10fd81179e4151929f60fec4dc50001ce87302e302e302e30808454f8483c");
PingMessage msg1 = (PingMessage)Message.decode(wire);
ECKey key = ECKey.fromPrivate(BigInteger.TEN);
PingMessage msg2 = PingMessage.create(msg1.getHost(), msg1.getPort(), key);
PingMessage msg3 = (PingMessage)Message.decode(msg2.getPacket());
assertEquals(msg1.getHost(), msg3.getHost());
}
@Test // Pong parse data
public void test10(){
// wire: 84db9bf6a1f7a3444f4d4946155da16c63a51abdd6822ac683d8243f260b99b265601b769acebfe3c76ddeb6e83e924f2bac2beca0c802ff0745d349bd58bc6662d62d38c2a3bb3e167a333d7d099496ebd35e096c5c1ee1587e9bd11f20e3d80002e6a079d49bdba3a7acfc9a2881d768d1aa246c2486ab166f0305a863bd47c5d21e0e8454f8483c
// PongMessage: {mdc=84db9bf6a1f7a3444f4d4946155da16c63a51abdd6822ac683d8243f260b99b2, signature=65601b769acebfe3c76ddeb6e83e924f2bac2beca0c802ff0745d349bd58bc6662d62d38c2a3bb3e167a333d7d099496ebd35e096c5c1ee1587e9bd11f20e3d800, type=02, data=e6a079d49bdba3a7acfc9a2881d768d1aa246c2486ab166f0305a863bd47c5d21e0e8454f8483c}
byte[] wire =
Hex.decode("84db9bf6a1f7a3444f4d4946155da16c63a51abdd6822ac683d8243f260b99b265601b769acebfe3c76ddeb6e83e924f2bac2beca0c802ff0745d349bd58bc6662d62d38c2a3bb3e167a333d7d099496ebd35e096c5c1ee1587e9bd11f20e3d80002e6a079d49bdba3a7acfc9a2881d768d1aa246c2486ab166f0305a863bd47c5d21e0e8454f8483c");
PongMessage msg1 = (PongMessage)Message.decode(wire);
ECKey key = ECKey.fromPrivate(BigInteger.TEN);
PongMessage msg2 = PongMessage.create(msg1.getToken(), key);
PongMessage msg3 = (PongMessage)Message.decode(msg2.getPacket());
assertEquals( Hex.toHexString(msg1.getToken()), Hex.toHexString(msg3.getToken()));
}
}

View File

@ -1,79 +0,0 @@
package test.ethereum.net;
import org.ethereum.net.eth.StatusMessage;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import static org.junit.Assert.assertEquals;
public class StatusMessageTest {
/* STATUS_MESSAGE */
private static final Logger logger = LoggerFactory.getLogger("test");
@Test
public void test1() {
String raw = "f84a1027808425c60144a0832056d3c93ff2739ace7199952e5365aa29f18805be05634c4db125c5340216a0955f36d073ccb026b78ab3424c15cf966a7563aa270413859f78702b9e8e22cb";
byte[] payload = Hex.decode(raw);
StatusMessage statusMessage = new StatusMessage(payload);
logger.info(statusMessage.toString());
assertEquals(39, statusMessage.getProtocolVersion());
assertEquals("25c60144",
Hex.toHexString(statusMessage.getTotalDifficulty()));
assertEquals("832056d3c93ff2739ace7199952e5365aa29f18805be05634c4db125c5340216",
Hex.toHexString(statusMessage.getBestHash()));
}
@Test //from constructor
public void test2() {
//Init
byte version = 39;
byte netId = 0;
byte[] difficulty = new BigInteger("25c60144", 16).toByteArray();
byte[] bestHash =
new BigInteger("832056d3c93ff2739ace7199952e5365aa29f18805be05634c4db125c5340216", 16).toByteArray();
byte[] genesisHash =
new BigInteger("955f36d073ccb026b78ab3424c15cf966a7563aa270413859f78702b9e8e22cb", 16).toByteArray();
StatusMessage statusMessage = new StatusMessage(version, netId, difficulty, bestHash, genesisHash);
logger.info(statusMessage.toString());
assertEquals(39, statusMessage.getProtocolVersion());
assertEquals("25c60144", Hex.toHexString(statusMessage.getTotalDifficulty()));
assertEquals("00832056d3c93ff2739ace7199952e5365aa29f18805be05634c4db125c5340216",
Hex.toHexString(statusMessage.getBestHash()));
assertEquals("00955f36d073ccb026b78ab3424c15cf966a7563aa270413859f78702b9e8e22cb",
Hex.toHexString(statusMessage.getGenesisHash()));
}
@Test //fail test
public void test3() {
//Init
byte version = -1; //invalid version
byte netId = -1; //invalid netid
byte[] difficulty = new BigInteger("-1000000", 16).toByteArray(); //negative difficulty
byte[] bestHash = new BigInteger("-100000000000000000000000000", 16).toByteArray(); //invalid hash
byte[] genesisHash = new BigInteger("-1000000000000000000000000000000", 16).toByteArray(); //invalid hash
StatusMessage statusMessage = new StatusMessage(version, netId, difficulty, bestHash, genesisHash);
logger.info(statusMessage.toString());
assertEquals(-1, statusMessage.getProtocolVersion());
assertEquals("ff000000", Hex.toHexString(statusMessage.getTotalDifficulty()));
assertEquals("ff00000000000000000000000000", Hex.toHexString(statusMessage.getBestHash()));
assertEquals("ff000000000000000000000000000000", Hex.toHexString(statusMessage.getGenesisHash()));
}
}

View File

@ -1,200 +0,0 @@
package test.ethereum.net;
import org.ethereum.core.Transaction;
import org.ethereum.crypto.ECKey;
import org.ethereum.crypto.HashUtil;
import org.ethereum.net.eth.EthMessageCodes;
import org.ethereum.net.eth.GetTransactionsMessage;
import org.ethereum.net.eth.TransactionsMessage;
import org.ethereum.util.ByteUtil;
import org.junit.Ignore;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import static org.junit.Assert.*;
public class TransactionsMessageTest {
/* GET_TRANSACTIONS */
@Test /* GetTransactions message 1 */
public void testGetTransactions() {
GetTransactionsMessage getTransactionsMessage = new GetTransactionsMessage();
System.out.println(getTransactionsMessage);
assertEquals(EthMessageCodes.GET_TRANSACTIONS, getTransactionsMessage.getCommand());
assertEquals(TransactionsMessage.class, getTransactionsMessage.getAnswerMessage());
}
/* TRANSACTIONS */
@Ignore
@Test /* Transactions message 1 */
public void test_1() {
String txsPacketRaw = "f86e12f86b04648609184e72a00094cd2a3d9f938e13cd947ec05abc7fe734df8dd826"
+ "881bc16d674ec80000801ba05c89ebf2b77eeab88251e553f6f9d53badc1d800"
+ "bbac02d830801c2aa94a4c9fa00b7907532b1f29c79942b75fff98822293bf5f"
+ "daa3653a8d9f424c6a3265f06c";
byte[] payload = Hex.decode(txsPacketRaw);
TransactionsMessage transactionsMessage = new TransactionsMessage(payload);
System.out.println(transactionsMessage);
assertEquals(EthMessageCodes.TRANSACTIONS, transactionsMessage.getCommand());
assertEquals(1, transactionsMessage.getTransactions().size());
Transaction tx = transactionsMessage.getTransactions().iterator().next();
assertEquals("5d2aee0490a9228024158433d650335116b4af5a30b8abb10e9b7f9f7e090fd8", Hex.toHexString(tx.getHash()));
assertEquals("04", Hex.toHexString(tx.getNonce()));
assertEquals("1bc16d674ec80000", Hex.toHexString(tx.getValue()));
assertEquals("cd2a3d9f938e13cd947ec05abc7fe734df8dd826", Hex.toHexString(tx.getReceiveAddress()));
assertEquals("64", Hex.toHexString(tx.getGasPrice()));
assertEquals("09184e72a000", Hex.toHexString(tx.getGasLimit()));
assertEquals("", ByteUtil.toHexString(tx.getData()));
assertEquals("1b", Hex.toHexString(new byte[]{tx.getSignature().v}));
assertEquals("5c89ebf2b77eeab88251e553f6f9d53badc1d800bbac02d830801c2aa94a4c9f", Hex.toHexString(tx.getSignature().r.toByteArray()));
assertEquals("0b7907532b1f29c79942b75fff98822293bf5fdaa3653a8d9f424c6a3265f06c", Hex.toHexString(tx.getSignature().s.toByteArray()));
}
@Ignore
@Test /* Transactions message 2 */
public void test_2() {
String txsPacketRaw = "f9025012f89d8080940000000000000000000000000000000000000000860918"
+ "4e72a000822710b3606956330c0d630000003359366000530a0d630000003359"
+ "602060005301356000533557604060005301600054630000000c588433606957"
+ "1ca07f6eb94576346488c6253197bde6a7e59ddc36f2773672c849402aa9c402"
+ "c3c4a06d254e662bf7450dd8d835160cbb053463fed0b53f2cdd7f3ea8731919"
+ "c8e8ccf901050180940000000000000000000000000000000000000000860918"
+ "4e72a000822710b85336630000002e59606956330c0d63000000155933ff3356"
+ "0d63000000275960003356576000335700630000005358600035560d63000000"
+ "3a590033560d63000000485960003356573360003557600035335700b84a7f4e"
+ "616d655265670000000000000000000000000000000000000000000000000030"
+ "57307f4e616d6552656700000000000000000000000000000000000000000000"
+ "00000057336069571ba04af15a0ec494aeac5b243c8a2690833faa74c0f73db1"
+ "f439d521c49c381513e9a05802e64939be5a1f9d4d614038fbd5479538c48795"
+ "614ef9c551477ecbdb49d2f8a6028094ccdeac59d35627b7de09332e819d5159"
+ "e7bb72508609184e72a000822710b84000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000000000002d0aceee"
+ "7e5ab874e22ccf8d1a649f59106d74e81ba0d05887574456c6de8f7a0d172342"
+ "c2cbdd4cf7afe15d9dbb8b75b748ba6791c9a01e87172a861f6c37b5a9e3a5d0"
+ "d7393152a7fbe41530e5bb8ac8f35433e5931b";
byte[] payload = Hex.decode(txsPacketRaw);
TransactionsMessage transactionsMessage = new TransactionsMessage(payload);
System.out.println(transactionsMessage);
assertEquals(EthMessageCodes.TRANSACTIONS, transactionsMessage.getCommand());
assertEquals(3, transactionsMessage.getTransactions().size());
Iterator<Transaction> txIter = transactionsMessage.getTransactions().iterator();
Transaction tx1 = txIter.next();
txIter.next(); // skip one
Transaction tx3 = txIter.next();
assertEquals("1b9d9456293cbcbc2f28a0fdc67028128ea571b033fb0e21d0ee00bcd6167e5d",
Hex.toHexString(tx3.getHash()));
assertEquals("00",
Hex.toHexString(tx3.getNonce()));
assertEquals("2710",
Hex.toHexString(tx3.getValue()));
assertEquals("09184e72a000",
Hex.toHexString(tx3.getReceiveAddress()));
assertNull(tx3.getGasPrice());
assertEquals("0000000000000000000000000000000000000000",
Hex.toHexString(tx3.getGasLimit()));
assertEquals("606956330c0d630000003359366000530a0d630000003359602060005301356000533557604060005301600054630000000c58",
Hex.toHexString(tx3.getData()));
assertEquals("33",
Hex.toHexString(new byte[]{tx3.getSignature().v}));
assertEquals("1c",
Hex.toHexString(tx3.getSignature().r.toByteArray()));
assertEquals("7f6eb94576346488c6253197bde6a7e59ddc36f2773672c849402aa9c402c3c4",
Hex.toHexString(tx3.getSignature().s.toByteArray()));
// Transaction #2
assertEquals("dde9543921850f41ca88e5401322cd7651c78a1e4deebd5ee385af8ac343f0ad",
Hex.toHexString(tx1.getHash()));
assertEquals("02",
Hex.toHexString(tx1.getNonce()));
assertEquals("2710",
Hex.toHexString(tx1.getValue()));
assertEquals("09184e72a000",
Hex.toHexString(tx1.getReceiveAddress()));
assertNull(tx1.getGasPrice());
assertEquals("ccdeac59d35627b7de09332e819d5159e7bb7250",
Hex.toHexString(tx1.getGasLimit()));
assertEquals
("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000002d0aceee7e5ab874e22ccf8d1a649f59106d74e8",
Hex.toHexString(tx1.getData()));
assertEquals("1b",
Hex.toHexString(new byte[]{tx1.getSignature().v}));
assertEquals("00d05887574456c6de8f7a0d172342c2cbdd4cf7afe15d9dbb8b75b748ba6791c9",
Hex.toHexString(tx1.getSignature().r.toByteArray()));
assertEquals("1e87172a861f6c37b5a9e3a5d0d7393152a7fbe41530e5bb8ac8f35433e5931b",
Hex.toHexString(tx1.getSignature().s.toByteArray()));
}
@Test /* Transactions msg encode */
public void test_3() throws Exception {
String expected =
"f87302f870808b00d3c21bcecceda10000009479b08ad8787060333663d19704909ee7b1903e588609184e72a000824255801ca00f410a70e42b2c9854a8421d32c87c370a2b9fff0a27f9f031bb4443681d73b5a018a7dc4c4f9dee9f3dc35cb96ca15859aa27e219a8e4a8547be6bd3206979858";
BigInteger value = new BigInteger("1000000000000000000000000");
byte[] privKey = HashUtil.sha3("cat".getBytes());
ECKey ecKey = ECKey.fromPrivate(privKey);
byte[] gasPrice = Hex.decode("09184e72a000");
byte[] gas = Hex.decode("4255");
Transaction tx = new Transaction(null, value.toByteArray(),
ecKey.getAddress(), gasPrice, gas, null);
tx.sign(privKey);
tx.getEncoded();
Set<Transaction> txs = new HashSet<>(Arrays.asList(tx));
TransactionsMessage transactionsMessage = new TransactionsMessage(txs);
assertEquals(EthMessageCodes.TRANSACTIONS, transactionsMessage.getCommand());
assertEquals(expected, Hex.toHexString(transactionsMessage.getEncoded()));
}
}

View File

@ -1,150 +0,0 @@
package test.ethereum.net.wire;
import org.ethereum.net.client.Capability;
import org.ethereum.net.eth.EthHandler;
import org.ethereum.net.eth.EthMessageCodes;
import org.ethereum.net.p2p.P2pHandler;
import org.ethereum.net.p2p.P2pMessageCodes;
import org.ethereum.net.shh.ShhHandler;
import org.ethereum.net.shh.ShhMessageCodes;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
/**
* @author Roman Mandeleil
* @since 15.10.2014
*/
public class AdaptiveMessageIdsTest {
@Before
public void setUp() {
EthMessageCodes.setOffset((byte) 0x00);
ShhMessageCodes.setOffset((byte) 0x00);
}
@After
public void tearDown() {
EthMessageCodes.setOffset((byte) 0x00);
ShhMessageCodes.setOffset((byte) 0x00);
}
@Test
public void test1() {
Assert.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());
}
@Test
public void test2() {
Assert.assertEquals(9, 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());
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());
}
@Test
public void test3() {
Assert.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());
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());
}
@Test
public void test4() {
P2pHandler p2pHandler = new P2pHandler();
List<Capability> capabilities = Arrays.asList(
new Capability(Capability.ETH, EthHandler.VERSION),
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());
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());
}
@Test // Capabilities should be read in alphabetical order
public void test5() {
P2pHandler p2pHandler = new P2pHandler();
List<Capability> capabilities = Arrays.asList(
new Capability(Capability.SHH, ShhHandler.VERSION),
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());
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());
}
}

View File

@ -1,59 +0,0 @@
package test.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

@ -1,933 +0,0 @@
package test.ethereum.trie;
import org.ethereum.datasource.KeyValueDataSource;
import org.ethereum.datasource.LevelDbDataSource;
import test.ethereum.db.MockDB;
import org.ethereum.core.AccountState;
import org.ethereum.db.DatabaseImpl;
import org.ethereum.trie.TrieImpl;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.junit.After;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import static org.ethereum.crypto.HashUtil.EMPTY_TRIE_HASH;
import static org.junit.Assert.*;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
public class TrieTest {
private static final Logger logger = LoggerFactory.getLogger("test");
private static String LONG_STRING = "1234567890abcdefghijklmnopqrstuvwxxzABCEFGHIJKLMNOPQRSTUVWXYZ";
private static String ROOT_HASH_EMPTY = Hex.toHexString(EMPTY_TRIE_HASH);
private static String c = "c";
private static String ca = "ca";
private static String cat = "cat";
private static String dog = "dog";
private static String doge = "doge";
private static String test = "test";
private static String dude = "dude";
private MockDB mockDb = new MockDB();
private MockDB mockDb_2 = new MockDB();
// ROOT: [ '\x16', A ]
// A: [ '', '', '', '', B, '', '', '', C, '', '', '', '', '', '', '', '' ]
// B: [ '\x00\x6f', D ]
// D: [ '', '', '', '', '', '', E, '', '', '', '', '', '', '', '', '', 'verb' ]
// E: [ '\x17', F ]
// F: [ '', '', '', '', '', '', G, '', '', '', '', '', '', '', '', '', 'puppy' ]
// G: [ '\x35', 'coin' ]
// C: [ '\x20\x6f\x72\x73\x65', 'stallion' ]
@After
public void closeMockDb() throws IOException {
mockDb.close();
mockDb_2.close();
}
@Test
public void testEmptyKey() {
TrieImpl trie = new TrieImpl(mockDb);
trie.update("", dog);
assertEquals(dog, new String(trie.get("")));
}
@Test
public void testInsertShortString() {
TrieImpl trie = new TrieImpl(mockDb);
trie.update(cat, dog);
assertEquals(dog, new String(trie.get(cat)));
}
@Test
public void testInsertLongString() {
TrieImpl trie = new TrieImpl(mockDb);
trie.update(cat, LONG_STRING);
assertEquals(LONG_STRING, new String(trie.get(cat)));
}
@Test
public void testInsertMultipleItems1() {
TrieImpl trie = new TrieImpl(mockDb);
trie.update(ca, dude);
assertEquals(dude, new String(trie.get(ca)));
trie.update(cat, dog);
assertEquals(dog, new String(trie.get(cat)));
trie.update(dog, test);
assertEquals(test, new String(trie.get(dog)));
trie.update(doge, LONG_STRING);
assertEquals(LONG_STRING, new String(trie.get(doge)));
trie.update(test, LONG_STRING);
assertEquals(LONG_STRING, new String(trie.get(test)));
// Test if everything is still there
assertEquals(dude, new String(trie.get(ca)));
assertEquals(dog, new String(trie.get(cat)));
assertEquals(test, new String(trie.get(dog)));
assertEquals(LONG_STRING, new String(trie.get(doge)));
assertEquals(LONG_STRING, new String(trie.get(test)));
}
@Test
public void testInsertMultipleItems2() {
TrieImpl trie = new TrieImpl(mockDb);
trie.update(cat, dog);
assertEquals(dog, new String(trie.get(cat)));
trie.update(ca, dude);
assertEquals(dude, new String(trie.get(ca)));
trie.update(doge, LONG_STRING);
assertEquals(LONG_STRING, new String(trie.get(doge)));
trie.update(dog, test);
assertEquals(test, new String(trie.get(dog)));
trie.update(test, LONG_STRING);
assertEquals(LONG_STRING, new String(trie.get(test)));
// Test if everything is still there
assertEquals(dog, new String(trie.get(cat)));
assertEquals(dude, new String(trie.get(ca)));
assertEquals(LONG_STRING, new String(trie.get(doge)));
assertEquals(test, new String(trie.get(dog)));
assertEquals(LONG_STRING, new String(trie.get(test)));
}
@Test
public void testUpdateShortToShortString() {
TrieImpl trie = new TrieImpl(mockDb);
trie.update(cat, dog);
assertEquals(dog, new String(trie.get(cat)));
trie.update(cat, dog + "1");
assertEquals(dog + "1", new String(trie.get(cat)));
}
@Test
public void testUpdateLongToLongString() {
TrieImpl trie = new TrieImpl(mockDb);
trie.update(cat, LONG_STRING);
assertEquals(LONG_STRING, new String(trie.get(cat)));
trie.update(cat, LONG_STRING + "1");
assertEquals(LONG_STRING + "1", new String(trie.get(cat)));
}
@Test
public void testUpdateShortToLongString() {
TrieImpl trie = new TrieImpl(mockDb);
trie.update(cat, dog);
assertEquals(dog, new String(trie.get(cat)));
trie.update(cat, LONG_STRING + "1");
assertEquals(LONG_STRING + "1", new String(trie.get(cat)));
}
@Test
public void testUpdateLongToShortString() {
TrieImpl trie = new TrieImpl(mockDb);
trie.update(cat, LONG_STRING);
assertEquals(LONG_STRING, new String(trie.get(cat)));
trie.update(cat, dog + "1");
assertEquals(dog + "1", new String(trie.get(cat)));
}
@Test
public void testDeleteShortString1() {
String ROOT_HASH_BEFORE = "a9539c810cc2e8fa20785bdd78ec36cc1dab4b41f0d531e80a5e5fd25c3037ee";
String ROOT_HASH_AFTER = "fc5120b4a711bca1f5bb54769525b11b3fb9a8d6ac0b8bf08cbb248770521758";
TrieImpl trie = new TrieImpl(mockDb);
trie.update(cat, dog);
assertEquals(dog, new String(trie.get(cat)));
trie.update(ca, dude);
assertEquals(dude, new String(trie.get(ca)));
assertEquals(ROOT_HASH_BEFORE, Hex.toHexString(trie.getRootHash()));
trie.delete(ca);
assertEquals("", new String(trie.get(ca)));
assertEquals(ROOT_HASH_AFTER, Hex.toHexString(trie.getRootHash()));
}
@Test
public void testDeleteShortString2() {
String ROOT_HASH_BEFORE = "a9539c810cc2e8fa20785bdd78ec36cc1dab4b41f0d531e80a5e5fd25c3037ee";
String ROOT_HASH_AFTER = "b25e1b5be78dbadf6c4e817c6d170bbb47e9916f8f6cc4607c5f3819ce98497b";
TrieImpl trie = new TrieImpl(mockDb);
trie.update(ca, dude);
assertEquals(dude, new String(trie.get(ca)));
trie.update(cat, dog);
assertEquals(dog, new String(trie.get(cat)));
assertEquals(ROOT_HASH_BEFORE, Hex.toHexString(trie.getRootHash()));
trie.delete(cat);
assertEquals("", new String(trie.get(cat)));
assertEquals(ROOT_HASH_AFTER, Hex.toHexString(trie.getRootHash()));
}
@Test
public void testDeleteShortString3() {
String ROOT_HASH_BEFORE = "778ab82a7e8236ea2ff7bb9cfa46688e7241c1fd445bf2941416881a6ee192eb";
String ROOT_HASH_AFTER = "05875807b8f3e735188d2479add82f96dee4db5aff00dc63f07a7e27d0deab65";
TrieImpl trie = new TrieImpl(mockDb);
trie.update(cat, dude);
assertEquals(dude, new String(trie.get(cat)));
trie.update(dog, test);
assertEquals(test, new String(trie.get(dog)));
assertEquals(ROOT_HASH_BEFORE, Hex.toHexString(trie.getRootHash()));
trie.delete(dog);
assertEquals("", new String(trie.get(dog)));
assertEquals(ROOT_HASH_AFTER, Hex.toHexString(trie.getRootHash()));
}
@Test
public void testDeleteLongString1() {
String ROOT_HASH_BEFORE = "318961a1c8f3724286e8e80d312352f01450bc4892c165cc7614e1c2e5a0012a";
String ROOT_HASH_AFTER = "63356ecf33b083e244122fca7a9b128cc7620d438d5d62e4f8b5168f1fb0527b";
TrieImpl trie = new TrieImpl(mockDb);
trie.update(cat, LONG_STRING);
assertEquals(LONG_STRING, new String(trie.get(cat)));
trie.update(dog, LONG_STRING);
assertEquals(LONG_STRING, new String(trie.get(dog)));
assertEquals(ROOT_HASH_BEFORE, Hex.toHexString(trie.getRootHash()));
trie.delete(dog);
assertEquals("", new String(trie.get(dog)));
assertEquals(ROOT_HASH_AFTER, Hex.toHexString(trie.getRootHash()));
}
@Test
public void testDeleteLongString2() {
String ROOT_HASH_BEFORE = "e020de34ca26f8d373ff2c0a8ac3a4cb9032bfa7a194c68330b7ac3584a1d388";
String ROOT_HASH_AFTER = "334511f0c4897677b782d13a6fa1e58e18de6b24879d57ced430bad5ac831cb2";
TrieImpl trie = new TrieImpl(mockDb);
trie.update(ca, LONG_STRING);
assertEquals(LONG_STRING, new String(trie.get(ca)));
trie.update(cat, LONG_STRING);
assertEquals(LONG_STRING, new String(trie.get(cat)));
assertEquals(ROOT_HASH_BEFORE, Hex.toHexString(trie.getRootHash()));
trie.delete(cat);
assertEquals("", new String(trie.get(cat)));
assertEquals(ROOT_HASH_AFTER, Hex.toHexString(trie.getRootHash()));
}
@Test
public void testDeleteLongString3() {
String ROOT_HASH_BEFORE = "e020de34ca26f8d373ff2c0a8ac3a4cb9032bfa7a194c68330b7ac3584a1d388";
String ROOT_HASH_AFTER = "63356ecf33b083e244122fca7a9b128cc7620d438d5d62e4f8b5168f1fb0527b";
TrieImpl trie = new TrieImpl(mockDb);
trie.update(cat, LONG_STRING);
assertEquals(LONG_STRING, new String(trie.get(cat)));
trie.update(ca, LONG_STRING);
assertEquals(LONG_STRING, new String(trie.get(ca)));
assertEquals(ROOT_HASH_BEFORE, Hex.toHexString(trie.getRootHash()));
trie.delete(ca);
assertEquals("", new String(trie.get(ca)));
assertEquals(ROOT_HASH_AFTER, Hex.toHexString(trie.getRootHash()));
}
@Test
public void testDeleteMultipleItems1() {
String ROOT_HASH_BEFORE = "3a784eddf1936515f0313b073f99e3bd65c38689021d24855f62a9601ea41717";
String ROOT_HASH_AFTER1 = "60a2e75cfa153c4af2783bd6cb48fd6bed84c6381bc2c8f02792c046b46c0653";
String ROOT_HASH_AFTER2 = "a84739b4762ddf15e3acc4e6957e5ab2bbfaaef00fe9d436a7369c6f058ec90d";
TrieImpl trie = new TrieImpl(mockDb);
trie.update(cat, dog);
assertEquals(dog, new String(trie.get(cat)));
trie.update(ca, dude);
assertEquals(dude, new String(trie.get(ca)));
trie.update(doge, LONG_STRING);
assertEquals(LONG_STRING, new String(trie.get(doge)));
trie.update(dog, test);
assertEquals(test, new String(trie.get(dog)));
trie.update(test, LONG_STRING);
assertEquals(LONG_STRING, new String(trie.get(test)));
assertEquals(ROOT_HASH_BEFORE, Hex.toHexString(trie.getRootHash()));
trie.delete(dog);
assertEquals("", new String(trie.get(dog)));
assertEquals(ROOT_HASH_AFTER1, Hex.toHexString(trie.getRootHash()));
trie.delete(test);
assertEquals("", new String(trie.get(test)));
assertEquals(ROOT_HASH_AFTER2, Hex.toHexString(trie.getRootHash()));
}
@Test
public void testDeleteMultipleItems2() {
String ROOT_HASH_BEFORE = "cf1ed2b6c4b6558f70ef0ecf76bfbee96af785cb5d5e7bfc37f9804ad8d0fb56";
String ROOT_HASH_AFTER1 = "f586af4a476ba853fca8cea1fbde27cd17d537d18f64269fe09b02aa7fe55a9e";
String ROOT_HASH_AFTER2 = "c59fdc16a80b11cc2f7a8b107bb0c954c0d8059e49c760ec3660eea64053ac91";
TrieImpl trie = new TrieImpl(mockDb);
trie.update(c, LONG_STRING);
assertEquals(LONG_STRING, new String(trie.get(c)));
trie.update(ca, LONG_STRING);
assertEquals(LONG_STRING, new String(trie.get(ca)));
trie.update(cat, LONG_STRING);
assertEquals(LONG_STRING, new String(trie.get(cat)));
assertEquals(ROOT_HASH_BEFORE, Hex.toHexString(trie.getRootHash()));
trie.delete(ca);
assertEquals("", new String(trie.get(ca)));
assertEquals(ROOT_HASH_AFTER1, Hex.toHexString(trie.getRootHash()));
trie.delete(cat);
assertEquals("", new String(trie.get(cat)));
assertEquals(ROOT_HASH_AFTER2, Hex.toHexString(trie.getRootHash()));
}
@Test
public void testDeleteAll() {
String ROOT_HASH_BEFORE = "a84739b4762ddf15e3acc4e6957e5ab2bbfaaef00fe9d436a7369c6f058ec90d";
TrieImpl trie = new TrieImpl(mockDb);
assertEquals(ROOT_HASH_EMPTY, Hex.toHexString(trie.getRootHash()));
trie.update(ca, dude);
trie.update(cat, dog);
trie.update(doge, LONG_STRING);
assertEquals(ROOT_HASH_BEFORE, Hex.toHexString(trie.getRootHash()));
trie.delete(ca);
trie.delete(cat);
trie.delete(doge);
assertEquals(ROOT_HASH_EMPTY, Hex.toHexString(trie.getRootHash()));
}
@Test
public void testTrieEquals() {
TrieImpl trie1 = new TrieImpl(mockDb);
TrieImpl trie2 = new TrieImpl(mockDb);
trie1.update(doge, LONG_STRING);
trie2.update(doge, LONG_STRING);
assertTrue("Expected tries to be equal", trie1.equals(trie2));
assertEquals(Hex.toHexString(trie1.getRootHash()), Hex.toHexString(trie2.getRootHash()));
trie1.update(dog, LONG_STRING);
trie2.update(cat, LONG_STRING);
assertFalse("Expected tries not to be equal", trie1.equals(trie2));
assertNotEquals(Hex.toHexString(trie1.getRootHash()), Hex.toHexString(trie2.getRootHash()));
}
@Ignore
@Test
public void testTrieSync() {
TrieImpl trie = new TrieImpl(mockDb);
trie.update(dog, LONG_STRING);
assertEquals("Expected no data in database", mockDb.getAddedItems(), 0);
trie.sync();
assertNotEquals("Expected data to be persisted", mockDb.getAddedItems(), 0);
}
@Ignore
@Test
public void TestTrieDirtyTracking() {
TrieImpl trie = new TrieImpl(mockDb);
trie.update(dog, LONG_STRING);
assertTrue("Expected trie to be dirty", trie.getCache().isDirty());
trie.sync();
assertFalse("Expected trie not to be dirty", trie.getCache().isDirty());
trie.update(test, LONG_STRING);
trie.getCache().undo();
assertFalse("Expected trie not to be dirty", trie.getCache().isDirty());
}
@Test
public void TestTrieReset() {
TrieImpl trie = new TrieImpl(mockDb);
trie.update(cat, LONG_STRING);
assertNotEquals("Expected cached nodes", 0, trie.getCache().getNodes().size());
trie.getCache().undo();
assertEquals("Expected no nodes after undo", 0, trie.getCache().getNodes().size());
}
@Test
public void testTrieCopy() {
TrieImpl trie = new TrieImpl(mockDb);
trie.update("doe", "reindeer");
TrieImpl trie2 = trie.copy();
assertNotEquals(trie.hashCode(), trie2.hashCode()); // avoid possibility that its just a reference copy
assertEquals(Hex.toHexString(trie.getRootHash()), Hex.toHexString(trie2.getRootHash()));
assertTrue(trie.equals(trie2));
}
@Test
public void testTrieUndo() {
TrieImpl trie = new TrieImpl(mockDb);
trie.update("doe", "reindeer");
assertEquals("11a0327cfcc5b7689b6b6d727e1f5f8846c1137caaa9fc871ba31b7cce1b703e", Hex.toHexString(trie.getRootHash()));
trie.sync();
trie.update("dog", "puppy");
assertEquals("05ae693aac2107336a79309e0c60b24a7aac6aa3edecaef593921500d33c63c4", Hex.toHexString(trie.getRootHash()));
trie.undo();
assertEquals("11a0327cfcc5b7689b6b6d727e1f5f8846c1137caaa9fc871ba31b7cce1b703e", Hex.toHexString(trie.getRootHash()));
}
// Using tests from: https://github.com/ethereum/tests/blob/master/trietest.json
@Test
public void testSingleItem() {
TrieImpl trie = new TrieImpl(mockDb);
trie.update("A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
assertEquals("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab", Hex.toHexString(trie.getRootHash()));
}
@Test
public void testDogs() {
TrieImpl trie = new TrieImpl(mockDb);
trie.update("doe", "reindeer");
assertEquals("11a0327cfcc5b7689b6b6d727e1f5f8846c1137caaa9fc871ba31b7cce1b703e", Hex.toHexString(trie.getRootHash()));
trie.update("dog", "puppy");
assertEquals("05ae693aac2107336a79309e0c60b24a7aac6aa3edecaef593921500d33c63c4", Hex.toHexString(trie.getRootHash()));
trie.update("dogglesworth", "cat");
assertEquals("8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3", Hex.toHexString(trie.getRootHash()));
}
@Test
public void testPuppy() {
TrieImpl trie = new TrieImpl(mockDb);
trie.update("do", "verb");
trie.update("doge", "coin");
trie.update("horse", "stallion");
trie.update("dog", "puppy");
assertEquals("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84", Hex.toHexString(trie.getRootHash()));
}
@Test
public void testEmptyValues() {
TrieImpl trie = new TrieImpl(mockDb);
trie.update("do", "verb");
trie.update("ether", "wookiedoo");
trie.update("horse", "stallion");
trie.update("shaman", "horse");
trie.update("doge", "coin");
trie.update("ether", "");
trie.update("dog", "puppy");
trie.update("shaman", "");
assertEquals("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84", Hex.toHexString(trie.getRootHash()));
}
@Test
public void testFoo() {
TrieImpl trie = new TrieImpl(mockDb);
trie.update("foo", "bar");
trie.update("food", "bat");
trie.update("food", "bass");
assertEquals("17beaa1648bafa633cda809c90c04af50fc8aed3cb40d16efbddee6fdf63c4c3", Hex.toHexString(trie.getRootHash()));
}
@Test
public void testSmallValues() {
TrieImpl trie = new TrieImpl(mockDb);
trie.update("be", "e");
trie.update("dog", "puppy");
trie.update("bed", "d");
assertEquals("3f67c7a47520f79faa29255d2d3c084a7a6df0453116ed7232ff10277a8be68b", Hex.toHexString(trie.getRootHash()));
}
@Test
public void testTesty() {
TrieImpl trie = new TrieImpl(mockDb);
trie.update("test", "test");
assertEquals("85d106d4edff3b7a4889e91251d0a87d7c17a1dda648ebdba8c6060825be23b8", Hex.toHexString(trie.getRootHash()));
trie.update("te", "testy");
assertEquals("8452568af70d8d140f58d941338542f645fcca50094b20f3c3d8c3df49337928", Hex.toHexString(trie.getRootHash()));
}
private final String randomDictionary = "spinneries, archipenko, prepotency, herniotomy, preexpress, relaxative, insolvably, debonnaire, apophysate, virtuality, cavalryman, utilizable, diagenesis, vitascopic, governessy, abranchial, cyanogenic, gratulated, signalment, predicable, subquality, crystalize, prosaicism, oenologist, repressive, impanelled, cockneyism, bordelaise, compigne, konstantin, predicated, unsublimed, hydrophane, phycomyces, capitalise, slippingly, untithable, unburnable, deoxidizer, misteacher, precorrect, disclaimer, solidified, neuraxitis, caravaning, betelgeuse, underprice, uninclosed, acrogynous, reirrigate, dazzlingly, chaffiness, corybantes, intumesced, intentness, superexert, abstrusely, astounding, pilgrimage, posttarsal, prayerless, nomologist, semibelted, frithstool, unstinging, ecalcarate, amputating, megascopic, graphalloy, platteland, adjacently, mingrelian, valentinus, appendical, unaccurate, coriaceous, waterworks, sympathize, doorkeeper, overguilty, flaggingly, admonitory, aeriferous, normocytic, parnellism, catafalque, odontiasis, apprentice, adulterous, mechanisma, wilderness, undivorced, reinterred, effleurage, pretrochal, phytogenic, swirlingly, herbarized, unresolved, classifier, diosmosing, microphage, consecrate, astarboard, predefying, predriving, lettergram, ungranular, overdozing, conferring, unfavorite, peacockish, coinciding, erythraeum, freeholder, zygophoric, imbitterer, centroidal, appendixes, grayfishes, enological, indiscreet, broadcloth, divulgated, anglophobe, stoopingly, bibliophil, laryngitis, separatist, estivating, bellarmine, greasiness, typhlology, xanthation, mortifying, endeavorer, aviatrices, unequalise, metastatic, leftwinger, apologizer, quatrefoil, nonfouling, bitartrate, outchiding, undeported, poussetted, haemolysis, asantehene, montgomery, unjoinable, cedarhurst, unfastener, nonvacuums, beauregard, animalized, polyphides, cannizzaro, gelatinoid, apologised, unscripted, tracheidal, subdiscoid, gravelling, variegated, interabang, inoperable, immortelle, laestrygon, duplicatus, proscience, deoxidised, manfulness, channelize, nondefense, ectomorphy, unimpelled, headwaiter, hexaemeric, derivation, prelexical, limitarian, nonionized, prorefugee, invariably, patronizer, paraplegia, redivision, occupative, unfaceable, hypomnesia, psalterium, doctorfish, gentlefolk, overrefine, heptastich, desirously, clarabelle, uneuphonic, autotelism, firewarden, timberjack, fumigation, drainpipes, spathulate, novelvelle, bicorporal, grisliness, unhesitant, supergiant, unpatented, womanpower, toastiness, multichord, paramnesia, undertrick, contrarily, neurogenic, gunmanship, settlement, brookville, gradualism, unossified, villanovan, ecospecies, organising, buckhannon, prefulfill, johnsonese, unforegone, unwrathful, dunderhead, erceldoune, unwadeable, refunction, understuff, swaggering, freckliest, telemachus, groundsill, outslidden, bolsheviks, recognizer, hemangioma, tarantella, muhammedan, talebearer, relocation, preemption, chachalaca, septuagint, ubiquitous, plexiglass, humoresque, biliverdin, tetraploid, capitoline, summerwood, undilating, undetested, meningitic, petrolatum, phytotoxic, adiphenine, flashlight, protectory, inwreathed, rawishness, tendrillar, hastefully, bananaquit, anarthrous, unbedimmed, herborized, decenniums, deprecated, karyotypic, squalidity, pomiferous, petroglyph, actinomere, peninsular, trigonally, androgenic, resistance, unassuming, frithstool, documental, eunuchised, interphone, thymbraeus, confirmand, expurgated, vegetation, myographic, plasmagene, spindrying, unlackeyed, foreknower, mythically, albescence, rebudgeted, implicitly, unmonastic, torricelli, mortarless, labialized, phenacaine, radiometry, sluggishly, understood, wiretapper, jacobitely, unbetrayed, stadholder, directress, emissaries, corelation, sensualize, uncurbable, permillage, tentacular, thriftless, demoralize, preimagine, iconoclast, acrobatism, firewarden, transpired, bluethroat, wanderjahr, groundable, pedestrian, unulcerous, preearthly, freelanced, sculleries, avengingly, visigothic, preharmony, bressummer, acceptable, unfoolable, predivider, overseeing, arcosolium, piriformis, needlecord, homebodies, sulphation, phantasmic, unsensible, unpackaged, isopiestic, cytophagic, butterlike, frizzliest, winklehawk, necrophile, mesothorax, cuchulainn, unrentable, untangible, unshifting, unfeasible, poetastric, extermined, gaillardia, nonpendent, harborside, pigsticker, infanthood, underrower, easterling, jockeyship, housebreak, horologium, undepicted, dysacousma, incurrable, editorship, unrelented, peritricha, interchaff, frothiness, underplant, proafrican, squareness, enigmatise, reconciled, nonnumeral, nonevident, hamantasch, victualing, watercolor, schrdinger, understand, butlerlike, hemiglobin, yankeeland";
@Test
public void testMasiveUpdate() {
boolean massiveUpdateTestEnabled = false;
if (massiveUpdateTestEnabled) {
List<String> randomWords = Arrays.asList(randomDictionary.split(","));
HashMap<String, String> testerMap = new HashMap<>();
TrieImpl trie = new TrieImpl(mockDb);
Random generator = new Random();
// Random insertion
for (int i = 0; i < 100000; ++i) {
int randomIndex1 = generator.nextInt(randomWords.size());
int randomIndex2 = generator.nextInt(randomWords.size());
String word1 = randomWords.get(randomIndex1).trim();
String word2 = randomWords.get(randomIndex2).trim();
trie.update(word1, word2);
testerMap.put(word1, word2);
}
int half = testerMap.size() / 2;
for (int r = 0; r < half; ++r) {
int randomIndex = generator.nextInt(randomWords.size());
String word1 = randomWords.get(randomIndex).trim();
testerMap.remove(word1);
trie.delete(word1);
}
trie.cleanCache();
trie.sync();
// Assert the result now
Iterator<String> keys = testerMap.keySet().iterator();
while (keys.hasNext()) {
String mapWord1 = keys.next();
String mapWord2 = testerMap.get(mapWord1);
String treeWord2 = new String(trie.get(mapWord1));
Assert.assertEquals(mapWord2, treeWord2);
}
}
}
@Ignore
@Test
public void reddisTest() throws URISyntaxException, IOException {
URL massiveUpload_1 = ClassLoader
.getSystemResource("trie/massive-upload.dmp");
File file = new File(massiveUpload_1.toURI());
List<String> strData = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
String dbName = "state";
long startTime = System.currentTimeMillis();
Jedis jedis = new Jedis("localhost");
jedis.flushAll();
Pipeline pipeline = jedis.pipelined();
Set<String> keys = jedis.keys("*");
System.out.println("before: all " + keys.size());
for (String aStrData : strData) {
String[] keyVal = aStrData.split("=");
if (keyVal[0].equals("*"))
pipeline.del(keyVal[1].getBytes());
else
pipeline.set(keyVal[0].getBytes(), keyVal[1].getBytes());
}
pipeline.sync();
keys = jedis.keys("*");
System.out.println("all " + keys.size());
for (String key : keys)
System.out.println(key + " -> " + jedis.get(key));
System.out.println("time: " + (System.currentTimeMillis() - startTime));
}
@Ignore
@Test
public void testMasiveDetermenisticUpdate() throws IOException, URISyntaxException {
// should be root: cfd77c0fcb037adefce1f4e2eb94381456a4746379d2896bb8f309c620436d30
URL massiveUpload_1 = ClassLoader
.getSystemResource("trie/massive-upload.dmp");
File file = new File(massiveUpload_1.toURI());
List<String> strData = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
// *** Part - 1 ***
// 1. load the data from massive-upload.dmp
// which includes deletes/upadtes (5000 operations)
TrieImpl trieSingle = new TrieImpl(mockDb_2);
for (String aStrData : strData) {
String[] keyVal = aStrData.split("=");
if (keyVal[0].equals("*"))
trieSingle.delete(keyVal[1].trim());
else
trieSingle.update(keyVal[0].trim(), keyVal[1].trim());
}
System.out.println("root_1: => " + Hex.toHexString(trieSingle.getRootHash()));
// *** Part - 2 ***
// pre. we use the same data from massive-upload.dmp
// which includes deletes/upadtes (100000 operations)
// 1. part of the data loaded
// 2. the trie cache sync to the db
// 3. the rest of the data loaded with part of the trie not in the cache
TrieImpl trie = new TrieImpl(mockDb);
for (int i = 0; i < 2000; ++i) {
String[] keyVal = strData.get(i).split("=");
if (keyVal[0].equals("*"))
trie.delete(keyVal[1].trim());
else
trie.update(keyVal[0].trim(), keyVal[1].trim());
}
trie.cleanCache();
trie.sync();
TrieImpl trie2 = new TrieImpl(mockDb, trie.getRootHash());
for (int i = 2000; i < strData.size(); ++i) {
String[] keyVal = strData.get(i).split("=");
if (keyVal[0].equals("*"))
trie2.delete(keyVal[1].trim());
else
trie2.update(keyVal[0].trim(), keyVal[1].trim());
}
System.out.println("root_2: => " + Hex.toHexString(trie2.getRootHash()));
assertEquals(trieSingle.getRootHash(), trie2.getRootHash());
}
@Test // tests saving keys to the file //
public void testMasiveUpdateFromDB() {
boolean massiveUpdateFromDBEnabled = false;
if (massiveUpdateFromDBEnabled) {
List<String> randomWords = Arrays.asList(randomDictionary.split(","));
Map<String, String> testerMap = new HashMap<>();
TrieImpl trie = new TrieImpl(mockDb);
Random generator = new Random();
// Random insertion
for (int i = 0; i < 50000; ++i) {
int randomIndex1 = generator.nextInt(randomWords.size());
int randomIndex2 = generator.nextInt(randomWords.size());
String word1 = randomWords.get(randomIndex1).trim();
String word2 = randomWords.get(randomIndex2).trim();
trie.update(word1, word2);
testerMap.put(word1, word2);
}
trie.cleanCache();
trie.sync();
// Assert the result now
Iterator<String> keys = testerMap.keySet().iterator();
while (keys.hasNext()) {
String mapWord1 = keys.next();
String mapWord2 = testerMap.get(mapWord1);
String treeWord2 = new String(trie.get(mapWord1));
Assert.assertEquals(mapWord2, treeWord2);
}
TrieImpl trie2 = new TrieImpl(mockDb, trie.getRootHash());
// Assert the result now
keys = testerMap.keySet().iterator();
while (keys.hasNext()) {
String mapWord1 = keys.next();
String mapWord2 = testerMap.get(mapWord1);
String treeWord2 = new String(trie2.get(mapWord1));
Assert.assertEquals(mapWord2, treeWord2);
}
}
}
@Test
public void testRollbackTrie() throws URISyntaxException, IOException {
TrieImpl trieSingle = new TrieImpl(mockDb);
URL massiveUpload_1 = ClassLoader
.getSystemResource("trie/massive-upload.dmp");
File file = new File(massiveUpload_1.toURI());
List<String> strData = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
List<byte[]> roots = new ArrayList<>();
Map<String, String> trieDumps = new HashMap<>();
for (int i = 0; i < 100; ++i) {
String[] keyVal = strData.get(i).split("=");
if (keyVal[0].equals("*"))
trieSingle.delete(keyVal[1].trim());
else
trieSingle.update(keyVal[0].trim(), keyVal[1].trim());
byte[] hash = trieSingle.getRootHash();
roots.add(hash);
String key = Hex.toHexString(hash);
String dump = trieSingle.getTrieDump();
trieDumps.put(key, dump);
}
// compare all 100 rollback dumps and
// the originaly saved dumps
for (int i = 1; i < roots.size(); ++i) {
byte[] root = roots.get(i);
logger.info("rollback over root : {}", Hex.toHexString(root));
trieSingle.setRoot(root);
String currDump = trieSingle.getTrieDump();
String originDump = trieDumps.get(Hex.toHexString(root));
// System.out.println(currDump);
Assert.assertEquals(currDump, originDump);
}
}
@Ignore
@Test
public void testGetFromRootNode() {
TrieImpl trie1 = new TrieImpl(mockDb);
trie1.update(cat, LONG_STRING);
trie1.sync();
TrieImpl trie2 = new TrieImpl(mockDb, trie1.getRootHash());
assertEquals(LONG_STRING, new String(trie2.get(cat)));
}
/*
0x7645b9fbf1b51e6b980801fafe6bbc22d2ebe218 0x517eaccda568f3fa24915fed8add49d3b743b3764c0bc495b19a47c54dbc3d62 0x 0x1
0x0000000000000000000000000000000000000000000000000000000000000010 0x947e70f9460402290a3e487dae01f610a1a8218fda
0x0000000000000000000000000000000000000000000000000000000000000014 0x40
0x0000000000000000000000000000000000000000000000000000000000000016 0x94412e0c4f0102f3f0ac63f0a125bce36ca75d4e0d
0x0000000000000000000000000000000000000000000000000000000000000017 0x01
*/
@Test
public void storageHashCalc_1() {
byte[] key1 = Hex.decode("0000000000000000000000000000000000000000000000000000000000000010");
byte[] key2 = Hex.decode("0000000000000000000000000000000000000000000000000000000000000014");
byte[] key3 = Hex.decode("0000000000000000000000000000000000000000000000000000000000000016");
byte[] key4 = Hex.decode("0000000000000000000000000000000000000000000000000000000000000017");
byte[] val1 = Hex.decode("947e70f9460402290a3e487dae01f610a1a8218fda");
byte[] val2 = Hex.decode("40");
byte[] val3 = Hex.decode("94412e0c4f0102f3f0ac63f0a125bce36ca75d4e0d");
byte[] val4 = Hex.decode("01");
TrieImpl storage = new TrieImpl(new MockDB());
storage.update(key1, val1);
storage.update(key2, val2);
storage.update(key3, val3);
storage.update(key4, val4);
String hash = Hex.toHexString(storage.getRootHash());
System.out.println(hash);
Assert.assertEquals("517eaccda568f3fa24915fed8add49d3b743b3764c0bc495b19a47c54dbc3d62", hash);
}
@Test
public void testFromDump_1() throws URISyntaxException, IOException, ParseException {
// LOAD: real dump from real state run
URL dbDump = ClassLoader
.getSystemResource("dbdump/dbdump.json");
File dbDumpFile = new File(dbDump.toURI());
byte[] testData = Files.readAllBytes(dbDumpFile.toPath());
String testSrc = new String(testData);
JSONParser parser = new JSONParser();
JSONArray dbDumpJSONArray = (JSONArray) parser.parse(testSrc);
KeyValueDataSource keyValueDataSource = new LevelDbDataSource("testState");
keyValueDataSource.init();
DatabaseImpl db = new DatabaseImpl(keyValueDataSource);
for (Object aDbDumpJSONArray : dbDumpJSONArray) {
JSONObject obj = (JSONObject) aDbDumpJSONArray;
byte[] key = Hex.decode(obj.get("key").toString());
byte[] val = Hex.decode(obj.get("val").toString());
db.put(key, val);
}
// TEST: load trie out of this run up to block#33
byte[] rootNode = Hex.decode("bb690805d24882bc7ccae6fc0f80ac146274d5b81c6a6e9c882cd9b0a649c9c7");
TrieImpl trie = new TrieImpl(db.getDb(), rootNode);
// first key added in genesis
byte[] val1 = trie.get(Hex.decode("51ba59315b3a95761d0863b05ccc7a7f54703d99"));
AccountState accountState1 = new AccountState(val1);
assertEquals(BigInteger.valueOf(2).pow(200), accountState1.getBalance());
assertEquals("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", Hex.toHexString(accountState1.getCodeHash()));
assertEquals(BigInteger.ZERO, accountState1.getNonce());
assertEquals(null, accountState1.getStateRoot());
// last key added up to block#33
byte[] val2 = trie.get(Hex.decode("a39c2067eb45bc878818946d0f05a836b3da44fa"));
AccountState accountState2 = new AccountState(val2);
assertEquals(new BigInteger("1500000000000000000"), accountState2.getBalance());
assertEquals("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", Hex.toHexString(accountState2.getCodeHash()));
assertEquals(BigInteger.ZERO, accountState2.getNonce());
assertEquals(null, accountState2.getStateRoot());
db.close();
}
@Test // update the trie with blog key/val
// each time dump the entire trie
public void testSample_1() {
TrieImpl trie = new TrieImpl(mockDb);
trie.update("dog", "puppy");
String dmp = trie.getTrieDump();
System.out.println(dmp);
System.out.println();
Assert.assertEquals("ed6e08740e4a267eca9d4740f71f573e9aabbcc739b16a2fa6c1baed5ec21278", Hex.toHexString(trie.getRootHash()));
trie.update("do", "verb");
dmp = trie.getTrieDump();
System.out.println(dmp);
System.out.println();
Assert.assertEquals("779db3986dd4f38416bfde49750ef7b13c6ecb3e2221620bcad9267e94604d36", Hex.toHexString(trie.getRootHash()));
trie.update("doggiestan", "aeswome_place");
dmp = trie.getTrieDump();
System.out.println(dmp);
System.out.println();
Assert.assertEquals("8bd5544747b4c44d1274aa99a6293065fe319b3230e800203317e4c75a770099", Hex.toHexString(trie.getRootHash()));
}
}

View File

@ -1,331 +0,0 @@
package test.ethereum.util;
import org.ethereum.util.ByteUtil;
import org.ethereum.util.FastByteComparisons;
import org.junit.Assert;
import org.junit.Test;
import org.spongycastle.util.BigIntegers;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
public class ByteUtilTest {
@Test
public void testAppendByte() {
byte[] bytes = "tes".getBytes();
byte b = 0x74;
Assert.assertArrayEquals("test".getBytes(), ByteUtil.appendByte(bytes, b));
}
@Test
public void testBigIntegerToBytes() {
byte[] expecteds = new byte[]{(byte) 0xff, (byte) 0xec, 0x78};
BigInteger b = BigInteger.valueOf(16772216);
byte[] actuals = ByteUtil.bigIntegerToBytes(b);
assertArrayEquals(expecteds, actuals);
}
@Test
public void testBigIntegerToBytesNegative() {
byte[] expecteds = new byte[]{(byte) 0xff, 0x0, 0x13, (byte) 0x88};
BigInteger b = BigInteger.valueOf(-16772216);
byte[] actuals = ByteUtil.bigIntegerToBytes(b);
assertArrayEquals(expecteds, actuals);
}
@Test
public void testBigIntegerToBytesZero() {
byte[] expecteds = new byte[]{0x00};
BigInteger b = BigInteger.ZERO;
byte[] actuals = ByteUtil.bigIntegerToBytes(b);
assertArrayEquals(expecteds, actuals);
}
@Test
public void testToHexString() {
assertEquals("", ByteUtil.toHexString(null));
}
@Test
public void testCalcPacketLength() {
byte[] test = new byte[]{0x0f, 0x10, 0x43};
byte[] expected = new byte[]{0x00, 0x00, 0x00, 0x03};
assertArrayEquals(expected, ByteUtil.calcPacketLength(test));
}
@Test
public void testByteArrayToInt() {
assertEquals(0, ByteUtil.byteArrayToInt(null));
assertEquals(0, ByteUtil.byteArrayToInt(new byte[0]));
// byte[] x = new byte[] { 5,1,7,0,8 };
// long start = System.currentTimeMillis();
// for (int i = 0; i < 100000000; i++) {
// ByteArray.read32bit(x, 0);
// }
// long end = System.currentTimeMillis();
// System.out.println(end - start + "ms");
//
// long start1 = System.currentTimeMillis();
// for (int i = 0; i < 100000000; i++) {
// new BigInteger(1, x).intValue();
// }
// long end1 = System.currentTimeMillis();
// System.out.println(end1 - start1 + "ms");
}
@Test
public void testNumBytes() {
String test1 = "0";
String test2 = "1";
String test3 = "1000000000"; //3B9ACA00
int expected1 = 1;
int expected2 = 1;
int expected3 = 4;
assertEquals(expected1, ByteUtil.numBytes(test1));
assertEquals(expected2, ByteUtil.numBytes(test2));
assertEquals(expected3, ByteUtil.numBytes(test3));
}
@Test
public void testStripLeadingZeroes() {
byte[] test1 = null;
byte[] test2 = new byte[]{};
byte[] test3 = new byte[]{0x00};
byte[] test4 = new byte[]{0x00, 0x01};
byte[] test5 = new byte[]{0x00, 0x00, 0x01};
byte[] expected1 = null;
byte[] expected2 = new byte[]{0};
byte[] expected3 = new byte[]{0};
byte[] expected4 = new byte[]{0x01};
byte[] expected5 = new byte[]{0x01};
assertArrayEquals(expected1, ByteUtil.stripLeadingZeroes(test1));
assertArrayEquals(expected2, ByteUtil.stripLeadingZeroes(test2));
assertArrayEquals(expected3, ByteUtil.stripLeadingZeroes(test3));
assertArrayEquals(expected4, ByteUtil.stripLeadingZeroes(test4));
assertArrayEquals(expected5, ByteUtil.stripLeadingZeroes(test5));
}
@Test
public void testMatchingNibbleLength1() {
// a larger than b
byte[] a = new byte[]{0x00, 0x01};
byte[] b = new byte[]{0x00};
int result = ByteUtil.matchingNibbleLength(a, b);
assertEquals(1, result);
}
@Test
public void testMatchingNibbleLength2() {
// b larger than a
byte[] a = new byte[]{0x00};
byte[] b = new byte[]{0x00, 0x01};
int result = ByteUtil.matchingNibbleLength(a, b);
assertEquals(1, result);
}
@Test
public void testMatchingNibbleLength3() {
// a and b the same length equal
byte[] a = new byte[]{0x00};
byte[] b = new byte[]{0x00};
int result = ByteUtil.matchingNibbleLength(a, b);
assertEquals(1, result);
}
@Test
public void testMatchingNibbleLength4() {
// a and b the same length not equal
byte[] a = new byte[]{0x01};
byte[] b = new byte[]{0x00};
int result = ByteUtil.matchingNibbleLength(a, b);
assertEquals(0, result);
}
@Test
public void testNiceNiblesOutput_1() {
byte[] test = {7, 0, 7, 5, 7, 0, 7, 0, 7, 9};
String result = "\\x07\\x00\\x07\\x05\\x07\\x00\\x07\\x00\\x07\\x09";
assertEquals(result, ByteUtil.nibblesToPrettyString(test));
}
@Test
public void testNiceNiblesOutput_2() {
byte[] test = {7, 0, 7, 0xf, 7, 0, 0xa, 0, 7, 9};
String result = "\\x07\\x00\\x07\\x0f\\x07\\x00\\x0a\\x00\\x07\\x09";
assertEquals(result, ByteUtil.nibblesToPrettyString(test));
}
@Test(expected = NullPointerException.class)
public void testMatchingNibbleLength5() {
// a == null
byte[] a = null;
byte[] b = new byte[]{0x00};
ByteUtil.matchingNibbleLength(a, b);
}
@Test(expected = NullPointerException.class)
public void testMatchingNibbleLength6() {
// b == null
byte[] a = new byte[]{0x00};
byte[] b = null;
ByteUtil.matchingNibbleLength(a, b);
}
@Test
public void testMatchingNibbleLength7() {
// a or b is empty
byte[] a = new byte[0];
byte[] b = new byte[]{0x00};
int result = ByteUtil.matchingNibbleLength(a, b);
assertEquals(0, result);
}
/**
* This test shows the difference between iterating over,
* and comparing byte[] vs BigInteger value.
*
* Results indicate that the former has ~15x better performance.
* Therefore this is used in the Miner.mine() method.
*/
@Test
public void testIncrementPerformance() {
boolean testEnabled = false;
if (testEnabled) {
byte[] counter1 = new byte[4];
byte[] max = ByteBuffer.allocate(4).putInt(Integer.MAX_VALUE).array();
long start1 = System.currentTimeMillis();
while (ByteUtil.increment(counter1)) {
if (FastByteComparisons.compareTo(counter1, 0, 4, max, 0, 4) == 0) {
break;
}
}
System.out.println(System.currentTimeMillis() - start1 + "ms to reach: " + Hex.toHexString(counter1));
BigInteger counter2 = BigInteger.ZERO;
long start2 = System.currentTimeMillis();
while (true) {
if (counter2.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) == 0) {
break;
}
counter2 = counter2.add(BigInteger.ONE);
}
System.out.println(System.currentTimeMillis() - start2 + "ms to reach: " + Hex.toHexString(BigIntegers.asUnsignedByteArray(4, counter2)));
}
}
@Test
public void firstNonZeroByte_1() {
byte[] data = Hex.decode("0000000000000000000000000000000000000000000000000000000000000000");
int result = ByteUtil.firstNonZeroByte(data);
assertEquals(-1, result);
}
@Test
public void firstNonZeroByte_2() {
byte[] data = Hex.decode("0000000000000000000000000000000000000000000000000000000000332211");
int result = ByteUtil.firstNonZeroByte(data);
assertEquals(29, result);
}
@Test
public void firstNonZeroByte_3() {
byte[] data = Hex.decode("2211009988776655443322110099887766554433221100998877665544332211");
int result = ByteUtil.firstNonZeroByte(data);
assertEquals(0, result);
}
@Test
public void setBitTest() {
/*
Set on
*/
byte[] data = ByteBuffer.allocate(4).putInt(0).array();
int posBit = 24;
int expected = 16777216;
int result = -1;
byte[] ret = ByteUtil.setBit(data, posBit, 1);
result = ByteUtil.byteArrayToInt(ret);
assertTrue(expected == result);
posBit = 25;
expected = 50331648;
ret = ByteUtil.setBit(data, posBit, 1);
result = ByteUtil.byteArrayToInt(ret);
assertTrue(expected == result);
posBit = 2;
expected = 50331652;
ret = ByteUtil.setBit(data, posBit, 1);
result = ByteUtil.byteArrayToInt(ret);
assertTrue(expected == result);
/*
Set off
*/
posBit = 24;
expected = 33554436;
ret = ByteUtil.setBit(data, posBit, 0);
result = ByteUtil.byteArrayToInt(ret);
assertTrue(expected == result);
posBit = 25;
expected = 4;
ret = ByteUtil.setBit(data, posBit, 0);
result = ByteUtil.byteArrayToInt(ret);
assertTrue(expected == result);
posBit = 2;
expected = 0;
ret = ByteUtil.setBit(data, posBit, 0);
result = ByteUtil.byteArrayToInt(ret);
assertTrue(expected == result);
}
@Test
public void getBitTest() {
byte[] data = ByteBuffer.allocate(4).putInt(0).array();
ByteUtil.setBit(data, 24, 1);
ByteUtil.setBit(data, 25, 1);
ByteUtil.setBit(data, 2, 1);
List<Integer> found = new ArrayList<>();
for (int i = 0; i < (data.length * 8); i++) {
int res = ByteUtil.getBit(data, i);
if (res == 1)
if (i != 24 && i != 25 && i != 2)
assertTrue(false);
else
found.add(i);
else {
if (i == 24 || i == 25 || i == 2)
assertTrue(false);
}
}
if (found.size() != 3)
assertTrue(false);
assertTrue(found.get(0) == 2);
assertTrue(found.get(1) == 24);
assertTrue(found.get(2) == 25);
}
}

View File

@ -1,89 +0,0 @@
package test.ethereum.util;
import org.ethereum.util.CompactEncoder;
import org.junit.Test;
import static org.junit.Assert.assertArrayEquals;
public class CompactEncoderTest {
private final static byte T = 16; // terminator
@Test
public void testCompactEncodeOddCompact() {
byte[] test = new byte[]{1, 2, 3, 4, 5};
byte[] expectedData = new byte[]{0x11, 0x23, 0x45};
assertArrayEquals("odd compact encode fail", expectedData, CompactEncoder.packNibbles(test));
}
@Test
public void testCompactEncodeEvenCompact() {
byte[] test = new byte[]{0, 1, 2, 3, 4, 5};
byte[] expectedData = new byte[]{0x00, 0x01, 0x23, 0x45};
assertArrayEquals("even compact encode fail", expectedData, CompactEncoder.packNibbles(test));
}
@Test
public void testCompactEncodeEvenTerminated() {
byte[] test = new byte[]{0, 15, 1, 12, 11, 8, T};
byte[] expectedData = new byte[]{0x20, 0x0f, 0x1c, (byte) 0xb8};
assertArrayEquals("even terminated compact encode fail", expectedData, CompactEncoder.packNibbles(test));
}
@Test
public void testCompactEncodeOddTerminated() {
byte[] test = new byte[]{15, 1, 12, 11, 8, T};
byte[] expectedData = new byte[]{0x3f, 0x1c, (byte) 0xb8};
assertArrayEquals("odd terminated compact encode fail", expectedData, CompactEncoder.packNibbles(test));
}
@Test
public void testCompactDecodeOddCompact() {
byte[] test = new byte[]{0x11, 0x23, 0x45};
byte[] expected = new byte[]{1, 2, 3, 4, 5};
assertArrayEquals("odd compact decode fail", expected, CompactEncoder.unpackToNibbles(test));
}
@Test
public void testCompactDecodeEvenCompact() {
byte[] test = new byte[]{0x00, 0x01, 0x23, 0x45};
byte[] expected = new byte[]{0, 1, 2, 3, 4, 5};
assertArrayEquals("even compact decode fail", expected, CompactEncoder.unpackToNibbles(test));
}
@Test
public void testCompactDecodeEvenTerminated() {
byte[] test = new byte[]{0x20, 0x0f, 0x1c, (byte) 0xb8};
byte[] expected = new byte[]{0, 15, 1, 12, 11, 8, T};
assertArrayEquals("even terminated compact decode fail", expected, CompactEncoder.unpackToNibbles(test));
}
@Test
public void testCompactDecodeOddTerminated() {
byte[] test = new byte[]{0x3f, 0x1c, (byte) 0xb8};
byte[] expected = new byte[]{15, 1, 12, 11, 8, T};
assertArrayEquals("odd terminated compact decode fail", expected, CompactEncoder.unpackToNibbles(test));
}
@Test
public void testCompactHexEncode_1() {
byte[] test = "stallion".getBytes();
byte[] result = new byte[]{7, 3, 7, 4, 6, 1, 6, 12, 6, 12, 6, 9, 6, 15, 6, 14, T};
assertArrayEquals(result, CompactEncoder.binToNibbles(test));
}
@Test
public void testCompactHexEncode_2() {
byte[] test = "verb".getBytes();
byte[] result = new byte[]{7, 6, 6, 5, 7, 2, 6, 2, T};
assertArrayEquals(result, CompactEncoder.binToNibbles(test));
}
@Test
public void testCompactHexEncode_3() {
byte[] test = "puppy".getBytes();
byte[] result = new byte[]{7, 0, 7, 5, 7, 0, 7, 0, 7, 9, T};
assertArrayEquals(result, CompactEncoder.binToNibbles(test));
}
}

View File

@ -1,87 +0,0 @@
package test.ethereum.util;
import org.ethereum.crypto.HashUtil;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
import static org.junit.Assert.assertEquals;
public class HashUtilTest {
@Test
public void testSha256_EmptyString() {
String expected1 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
String result1 = Hex.toHexString(HashUtil.sha256(new byte[0]));
assertEquals(expected1, result1);
}
@Test
public void testSha256_Test() {
String expected2 = "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08";
String result2 = Hex.toHexString(HashUtil.sha256("test".getBytes()));
assertEquals(expected2, result2);
}
@Test
public void testSha256_Multiple() {
String expected1 = "1b4f0e9851971998e732078544c96b36c3d01cedf7caa332359d6f1d83567014";
String result1 = Hex.toHexString(HashUtil.sha256("test1".getBytes()));
assertEquals(expected1, result1);
String expected2 = "60303ae22b998861bce3b28f33eec1be758a213c86c93c076dbe9f558c11c752";
String result2 = Hex.toHexString(HashUtil.sha256("test2".getBytes()));
assertEquals(expected2, result2);
}
@Test
public void testSha3_EmptyString() {
String expected1 = "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470";
String result1 = Hex.toHexString(HashUtil.sha3(new byte[0]));
assertEquals(expected1, result1);
}
@Test
public void testSha3_Test() {
String expected2 = "9c22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658";
String result2 = Hex.toHexString(HashUtil.sha3("test".getBytes()));
assertEquals(expected2, result2);
}
@Test
public void testSha3_Multiple() {
String expected1 = "6d255fc3390ee6b41191da315958b7d6a1e5b17904cc7683558f98acc57977b4";
String result1 = Hex.toHexString(HashUtil.sha3("test1".getBytes()));
assertEquals(expected1, result1);
String expected2 = "4da432f1ecd4c0ac028ebde3a3f78510a21d54087b161590a63080d33b702b8d";
String result2 = Hex.toHexString(HashUtil.sha3("test2".getBytes()));
assertEquals(expected2, result2);
}
@Test
public void testRIPEMD160_EmptyString() {
String expected1 = "9c1185a5c5e9fc54612808977ee8f548b2258d31";
String result1 = Hex.toHexString(HashUtil.ripemd160(new byte[0]));
assertEquals(expected1, result1);
}
@Test
public void testRIPEMD160_Test() {
String expected2 = "5e52fee47e6b070565f74372468cdc699de89107";
String result2 = Hex.toHexString(HashUtil.ripemd160("test".getBytes()));
assertEquals(expected2, result2);
}
@Test
public void testRIPEMD160_Multiple() {
String expected1 = "9295fac879006ff44812e43b83b515a06c2950aa";
String result1 = Hex.toHexString(HashUtil.ripemd160("test1".getBytes()));
assertEquals(expected1, result1);
String expected2 = "80b85ebf641abccdd26e327c5782353137a0a0af";
String result2 = Hex.toHexString(HashUtil.ripemd160("test2".getBytes()));
assertEquals(expected2, result2);
}
}

File diff suppressed because one or more lines are too long

View File

@ -1,59 +0,0 @@
package test.ethereum.util;
import java.math.BigInteger;
public class RlpTestData {
/***********************************
* https://github.com/ethereum/tests/blob/master/rlptest.txt
*/
public static int test01 = 0;
public static String result01 = "80";
public static String test02 = "";
public static String result02 = "80";
public static String test03 = "d";
public static String result03 = "64";
public static String test04 = "cat";
public static String result04 = "83636174";
public static String test05 = "dog";
public static String result05 = "83646f67";
public static String[] test06 = new String[]{"cat", "dog"};
public static String result06 = "c88363617483646f67";
public static String[] test07 = new String[]{"dog", "god", "cat"};
public static String result07 = "cc83646f6783676f6483636174";
public static int test08 = 1;
public static String result08 = "01";
public static int test09 = 10;
public static String result09 = "0a";
public static int test10 = 100;
public static String result10 = "64";
public static int test11 = 1000;
public static String result11 = "8203e8";
public static BigInteger test12 = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639935");
public static String result12 = "a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
public static BigInteger test13 = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639936");
public static String result13 = "a1010000000000000000000000000000000000000000000000000000000000000000";
public static Object[] test14 = new Object[]{1, 2, new Object[]{}};
public static String result14 = "c30102c0";
public static Object[] expected14 = new Object[]{new byte[]{1}, new byte[]{2}, new Object[]{}};
public static Object[] test15 = new Object[]{new Object[]{new Object[]{}, new Object[]{}}, new Object[]{}};
public static String result15 = "c4c2c0c0c0";
public static Object[] test16 = new Object[]{"zw", new Object[]{4}, "wz"};
public static String result16 = "c8827a77c10482777a";
public static Object[] expected16 = new Object[]{new byte[]{122, 119}, new Object[]{new byte[]{4}}, new byte[]{119, 122}};
}

View File

@ -1,92 +0,0 @@
package test.ethereum.util;
import org.ethereum.util.Utils;
import org.junit.Test;
import org.spongycastle.util.Arrays;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import static org.junit.Assert.assertEquals;
/**
* @author Roman Mandeleil
* @since 17.05.14
*/
public class UtilsTest {
@Test
public void testGetValueShortString1() {
String expected = "123·(10^24)";
String result = Utils.getValueShortString(new BigInteger("123456789123445654363653463"));
assertEquals(expected, result);
}
@Test
public void testGetValueShortString2() {
String expected = "123·(10^3)";
String result = Utils.getValueShortString(new BigInteger("123456"));
assertEquals(expected, result);
}
@Test
public void testGetValueShortString3() {
String expected = "1·(10^3)";
String result = Utils.getValueShortString(new BigInteger("1234"));
assertEquals(expected, result);
}
@Test
public void testGetValueShortString4() {
String expected = "123·(10^0)";
String result = Utils.getValueShortString(new BigInteger("123"));
assertEquals(expected, result);
}
@Test
public void testGetValueShortString5() {
byte[] decimal = Hex.decode("3913517ebd3c0c65000000");
String expected = "69·(10^24)";
String result = Utils.getValueShortString(new BigInteger(decimal));
assertEquals(expected, result);
}
@Test
public void testAddressStringToBytes() {
// valid address
String HexStr = "6c386a4b26f73c802f34673f7248bb118f97424a";
byte[] expected = Hex.decode(HexStr);
byte[] result = Utils.addressStringToBytes(HexStr);
assertEquals(Arrays.areEqual(expected, result), true);
// invalid address, we removed the last char so it cannot decode
HexStr = "6c386a4b26f73c802f34673f7248bb118f97424";
expected = null;
result = Utils.addressStringToBytes(HexStr);
assertEquals(expected, result);
// invalid address, longer than 20 bytes
HexStr = new String(Hex.encode("I am longer than 20 bytes, i promise".getBytes()));
expected = null;
result = Utils.addressStringToBytes(HexStr);
assertEquals(expected, result);
// invalid address, shorter than 20 bytes
HexStr = new String(Hex.encode("I am short".getBytes()));
expected = null;
result = Utils.addressStringToBytes(HexStr);
assertEquals(expected, result);
}
}

View File

@ -1,63 +0,0 @@
package test.ethereum.util;
import org.ethereum.util.Value;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.util.Arrays;
import static org.junit.Assert.*;
public class ValueTest {
@Test
public void testCmp() {
Value val1 = new Value("hello");
Value val2 = new Value("world");
assertFalse("Expected values not to be equal", val1.cmp(val2));
Value val3 = new Value("hello");
Value val4 = new Value("hello");
assertTrue("Expected values to be equal", val3.cmp(val4));
}
@Test
public void testTypes() {
Value str = new Value("str");
assertEquals(str.asString(), "str");
Value num = new Value(1);
assertEquals(num.asInt(), 1);
Value inter = new Value(new Object[]{1});
Object[] interExp = new Object[]{1};
assertTrue(new Value(inter.asObj()).cmp(new Value(interExp)));
Value byt = new Value(new byte[]{1, 2, 3, 4});
byte[] bytExp = new byte[]{1, 2, 3, 4};
assertTrue(Arrays.equals(byt.asBytes(), bytExp));
Value bigInt = new Value(BigInteger.valueOf(10));
BigInteger bigExp = BigInteger.valueOf(10);
assertEquals(bigInt.asBigInt(), bigExp);
}
@Test
public void longListRLPBug_1() {
String testRlp = "f7808080d387206f72726563748a626574656c676575736580d387207870726573738a70726564696361626c658080808080808080808080";
Value val = Value.fromRlpEncoded(Hex.decode(testRlp));
assertEquals(testRlp, Hex.toHexString(val.encode()));
}
}

View File

@ -1,324 +0,0 @@
package test.ethereum.vm;
import org.ethereum.vm.DataWord;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class DataWordTest {
@Test
public void testAddPerformance() {
boolean enabled = false;
if (enabled) {
byte[] one = new byte[]{0x01, 0x31, 0x54, 0x41, 0x01, 0x31, 0x54,
0x41, 0x01, 0x31, 0x54, 0x41, 0x01, 0x31, 0x54, 0x41, 0x01,
0x31, 0x54, 0x41, 0x01, 0x31, 0x54, 0x41, 0x01, 0x31, 0x54,
0x41, 0x01, 0x31, 0x54, 0x41}; // Random value
int ITERATIONS = 10000000;
long now1 = System.currentTimeMillis();
for (int i = 0; i < ITERATIONS; i++) {
DataWord x = new DataWord(one);
x.add(x);
}
System.out.println("Add1: " + (System.currentTimeMillis() - now1) + "ms");
long now2 = System.currentTimeMillis();
for (int i = 0; i < ITERATIONS; i++) {
DataWord x = new DataWord(one);
x.add2(x);
}
System.out.println("Add2: " + (System.currentTimeMillis() - now2) + "ms");
} else {
System.out.println("ADD performance test is disabled.");
}
}
@Test
public void testAdd2() {
byte[] two = new byte[32];
two[31] = (byte) 0xff; // 0x000000000000000000000000000000000000000000000000000000000000ff
DataWord x = new DataWord(two);
x.add(new DataWord(two));
System.out.println(Hex.toHexString(x.getData()));
DataWord y = new DataWord(two);
y.add2(new DataWord(two));
System.out.println(Hex.toHexString(y.getData()));
}
@Test
public void testAdd3() {
byte[] three = new byte[32];
for (int i = 0; i < three.length; i++) {
three[i] = (byte) 0xff;
}
DataWord x = new DataWord(three);
x.add(new DataWord(three));
assertEquals(32, x.getData().length);
System.out.println(Hex.toHexString(x.getData()));
// FAIL
// DataWord y = new DataWord(three);
// y.add2(new DataWord(three));
// System.out.println(Hex.toHexString(y.getData()));
}
@Test
public void testMod() {
String expected = "000000000000000000000000000000000000000000000000000000000000001a";
byte[] one = new byte[32];
one[31] = 0x1e; // 0x000000000000000000000000000000000000000000000000000000000000001e
byte[] two = new byte[32];
for (int i = 0; i < two.length; i++) {
two[i] = (byte) 0xff;
}
two[31] = 0x56; // 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff56
DataWord x = new DataWord(one);// System.out.println(x.value());
DataWord y = new DataWord(two);// System.out.println(y.value());
y.mod(x);
assertEquals(32, y.getData().length);
assertEquals(expected, Hex.toHexString(y.getData()));
}
@Test
public void testMul() {
byte[] one = new byte[32];
one[31] = 0x1; // 0x0000000000000000000000000000000000000000000000000000000000000001
byte[] two = new byte[32];
two[11] = 0x1; // 0x0000000000000000000000010000000000000000000000000000000000000000
DataWord x = new DataWord(one);// System.out.println(x.value());
DataWord y = new DataWord(two);// System.out.println(y.value());
x.mul(y);
assertEquals(32, y.getData().length);
assertEquals("0000000000000000000000010000000000000000000000000000000000000000", Hex.toHexString(y.getData()));
}
@Test
public void testMulOverflow() {
byte[] one = new byte[32];
one[30] = 0x1; // 0x0000000000000000000000000000000000000000000000000000000000000100
byte[] two = new byte[32];
two[0] = 0x1; // 0x1000000000000000000000000000000000000000000000000000000000000000
DataWord x = new DataWord(one);// System.out.println(x.value());
DataWord y = new DataWord(two);// System.out.println(y.value());
x.mul(y);
assertEquals(32, y.getData().length);
assertEquals("0100000000000000000000000000000000000000000000000000000000000000", Hex.toHexString(y.getData()));
}
@Test
public void testDiv() {
byte[] one = new byte[32];
one[30] = 0x01;
one[31] = 0x2c; // 0x000000000000000000000000000000000000000000000000000000000000012c
byte[] two = new byte[32];
two[31] = 0x0f; // 0x000000000000000000000000000000000000000000000000000000000000000f
DataWord x = new DataWord(one);
DataWord y = new DataWord(two);
x.div(y);
assertEquals(32, x.getData().length);
assertEquals("0000000000000000000000000000000000000000000000000000000000000014", Hex.toHexString(x.getData()));
}
@Test
public void testDivZero() {
byte[] one = new byte[32];
one[30] = 0x05; // 0x0000000000000000000000000000000000000000000000000000000000000500
byte[] two = new byte[32];
DataWord x = new DataWord(one);
DataWord y = new DataWord(two);
x.div(y);
assertEquals(32, x.getData().length);
assertTrue(x.isZero());
}
@Test
public void testSDivNegative() {
// one is -300 as 256-bit signed integer:
byte[] one = Hex.decode("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed4");
byte[] two = new byte[32];
two[31] = 0x0f;
DataWord x = new DataWord(one);
DataWord y = new DataWord(two);
x.sDiv(y);
assertEquals(32, x.getData().length);
assertEquals("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec", x.toString());
}
@Test
public void testPow() {
BigInteger x = BigInteger.valueOf(Integer.MAX_VALUE);
BigInteger y = BigInteger.valueOf(1000);
BigInteger result1 = x.modPow(x, y);
BigInteger result2 = pow(x, y);
System.out.println(result1);
System.out.println(result2);
}
@Test
public void testSignExtend1() {
DataWord x = new DataWord(Hex.decode("f2"));
byte k = 0;
String expected = "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2";
x.signExtend(k);
System.out.println(x.toString());
assertEquals(expected, x.toString());
}
@Test
public void testSignExtend2() {
DataWord x = new DataWord(Hex.decode("f2"));
byte k = 1;
String expected = "00000000000000000000000000000000000000000000000000000000000000f2";
x.signExtend(k);
System.out.println(x.toString());
assertEquals(expected, x.toString());
}
@Test
public void testSignExtend3() {
byte k = 1;
DataWord x = new DataWord(Hex.decode("0f00ab"));
String expected = "00000000000000000000000000000000000000000000000000000000000000ab";
x.signExtend(k);
System.out.println(x.toString());
assertEquals(expected, x.toString());
}
@Test
public void testSignExtend4() {
byte k = 1;
DataWord x = new DataWord(Hex.decode("ffff"));
String expected = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
x.signExtend(k);
System.out.println(x.toString());
assertEquals(expected, x.toString());
}
@Test
public void testSignExtend5() {
byte k = 3;
DataWord x = new DataWord(Hex.decode("ffffffff"));
String expected = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
x.signExtend(k);
System.out.println(x.toString());
assertEquals(expected, x.toString());
}
@Test
public void testSignExtend6() {
byte k = 3;
DataWord x = new DataWord(Hex.decode("ab02345678"));
String expected = "0000000000000000000000000000000000000000000000000000000002345678";
x.signExtend(k);
System.out.println(x.toString());
assertEquals(expected, x.toString());
}
@Test
public void testSignExtend7() {
byte k = 3;
DataWord x = new DataWord(Hex.decode("ab82345678"));
String expected = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff82345678";
x.signExtend(k);
System.out.println(x.toString());
assertEquals(expected, x.toString());
}
@Test
public void testSignExtend8() {
byte k = 30;
DataWord x = new DataWord(Hex.decode("ff34567882345678823456788234567882345678823456788234567882345678"));
String expected = "0034567882345678823456788234567882345678823456788234567882345678";
x.signExtend(k);
System.out.println(x.toString());
assertEquals(expected, x.toString());
}
@Test(expected = IndexOutOfBoundsException.class)
public void testSignExtendException1() {
byte k = -1;
DataWord x = new DataWord();
x.signExtend(k); // should throw an exception
}
@Test(expected = IndexOutOfBoundsException.class)
public void testSignExtendException2() {
byte k = 32;
DataWord x = new DataWord();
x.signExtend(k); // should throw an exception
}
public static BigInteger pow(BigInteger x, BigInteger y) {
if (y.compareTo(BigInteger.ZERO) < 0)
throw new IllegalArgumentException();
BigInteger z = x; // z will successively become x^2, x^4, x^8, x^16,
// x^32...
BigInteger result = BigInteger.ONE;
byte[] bytes = y.toByteArray();
for (int i = bytes.length - 1; i >= 0; i--) {
byte bits = bytes[i];
for (int j = 0; j < 8; j++) {
if ((bits & 1) != 0)
result = result.multiply(z);
// short cut out if there are no more bits to handle:
if ((bits >>= 1) == 0 && i == 0)
return result;
z = z.multiply(z);
}
}
return result;
}
}

View File

@ -1,102 +0,0 @@
package test.ethereum.vm;
import org.ethereum.util.ByteUtil;
import org.ethereum.vm.DataWord;
import org.ethereum.vm.PrecompiledContracts;
import org.ethereum.vm.PrecompiledContracts.PrecompiledContract;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
import static org.junit.Assert.*;
/**
* @author Roman Mandeleil
*/
public class PrecompiledContractTest {
@Test
public void identityTest1() {
DataWord addr = new DataWord("0000000000000000000000000000000000000000000000000000000000000004");
PrecompiledContract contract = PrecompiledContracts.getContractForAddress(addr);
byte[] data = Hex.decode("112233445566");
byte[] expected = Hex.decode("112233445566");
byte[] result = contract.execute(data);
assertArrayEquals(expected, result);
}
@Test
public void sha256Test1() {
DataWord addr = new DataWord("0000000000000000000000000000000000000000000000000000000000000002");
PrecompiledContract contract = PrecompiledContracts.getContractForAddress(addr);
byte[] data = null;
String expected = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
byte[] result = contract.execute(data);
assertEquals(expected, Hex.toHexString(result));
}
@Test
public void sha256Test2() {
DataWord addr = new DataWord("0000000000000000000000000000000000000000000000000000000000000002");
PrecompiledContract contract = PrecompiledContracts.getContractForAddress(addr);
byte[] data = ByteUtil.EMPTY_BYTE_ARRAY;
String expected = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
byte[] result = contract.execute(data);
assertEquals(expected, Hex.toHexString(result));
}
@Test
public void sha256Test3() {
DataWord addr = new DataWord("0000000000000000000000000000000000000000000000000000000000000002");
PrecompiledContract contract = PrecompiledContracts.getContractForAddress(addr);
byte[] data = Hex.decode("112233");
String expected = "49ee2bf93aac3b1fb4117e59095e07abe555c3383b38d608da37680a406096e8";
byte[] result = contract.execute(data);
assertEquals(expected, Hex.toHexString(result));
}
@Test
public void Ripempd160Test1() {
DataWord addr = new DataWord("0000000000000000000000000000000000000000000000000000000000000003");
PrecompiledContract contract = PrecompiledContracts.getContractForAddress(addr);
byte[] data = Hex.decode("0000000000000000000000000000000000000000000000000000000000000001");
String expected = "000000000000000000000000ae387fcfeb723c3f5964509af111cf5a67f30661";
byte[] result = contract.execute(data);
assertEquals(expected, Hex.toHexString(result));
}
@Test
public void ecRecoverTest1() {
byte[] data = Hex.decode("18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549");
DataWord addr = new DataWord("0000000000000000000000000000000000000000000000000000000000000001");
PrecompiledContract contract = PrecompiledContracts.getContractForAddress(addr);
String expected = "000000000000000000000000ae387fcfeb723c3f5964509af111cf5a67f30661";
byte[] result = contract.execute(data);
System.out.println(Hex.toHexString(result));
}
}

View File

@ -1,338 +0,0 @@
package test.ethereum.vm;
import org.ethereum.util.ByteUtil;
import org.ethereum.vm.Program;
import org.ethereum.vm.ProgramInvokeMockImpl;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import java.nio.ByteBuffer;
import static org.junit.Assert.*;
public class ProgramMemoryTest {
ProgramInvokeMockImpl pi = null;
Program program;
ByteBuffer memory;
@Before
public void createProgram() {
program = new Program(ByteUtil.EMPTY_BYTE_ARRAY, pi);
}
@Test
public void testGetMemSize() {
ByteBuffer memory = ByteBuffer.allocate(64);
program.initMem(memory);
assertEquals(64, program.getMemSize());
}
@Test
@Ignore
public void testMemorySave() {
fail("Not yet implemented");
}
@Test
@Ignore
public void testMemoryLoad() {
fail("Not yet implemented");
}
@Test
public void testMemoryChunk1() {
program.initMem(ByteBuffer.allocate(64));
int offset = 128;
int size = 32;
program.memoryChunk(offset, size);
assertEquals(160, program.getMemSize());
}
@Test // size 0 doesn't increate memory
public void testMemoryChunk2() {
program.initMem(ByteBuffer.allocate(64));
int offset = 96;
int size = 0;
program.memoryChunk(offset, size);
assertEquals(64, program.getMemSize());
}
@Test
public void testAllocateMemory1() {
program.initMem(ByteBuffer.allocate(64));
int offset = 32;
int size = 32;
program.allocateMemory(offset, size);
assertEquals(64, program.getMemSize());
}
@Test
public void testAllocateMemory2() {
// memory.limit() > offset, == size
// memory.limit() < offset + size
program.initMem(ByteBuffer.allocate(64));
int offset = 32;
int size = 64;
program.allocateMemory(offset, size);
assertEquals(96, program.getMemSize());
}
@Test
public void testAllocateMemory3() {
// memory.limit() > offset, > size
program.initMem(ByteBuffer.allocate(64));
int offset = 0;
int size = 32;
program.allocateMemory(offset, size);
assertEquals(64, program.getMemSize());
}
@Test
public void testAllocateMemory4() {
program.initMem(ByteBuffer.allocate(64));
int offset = 0;
int size = 64;
program.allocateMemory(offset, size);
assertEquals(64, program.getMemSize());
}
@Test
public void testAllocateMemory5() {
program.initMem(ByteBuffer.allocate(64));
int offset = 0;
int size = 0;
program.allocateMemory(offset, size);
assertEquals(64, program.getMemSize());
}
@Test
public void testAllocateMemory6() {
// memory.limit() == offset, > size
program.initMem(ByteBuffer.allocate(64));
int offset = 64;
int size = 32;
program.allocateMemory(offset, size);
assertEquals(96, program.getMemSize());
}
@Test
public void testAllocateMemory7() {
// memory.limit() == offset - size
program.initMem(ByteBuffer.allocate(64));
int offset = 96;
int size = 32;
program.allocateMemory(offset, size);
assertEquals(128, program.getMemSize());
}
@Test
public void testAllocateMemory8() {
program.initMem(ByteBuffer.allocate(64));
int offset = 0;
int size = 96;
program.allocateMemory(offset, size);
assertEquals(96, program.getMemSize());
}
@Test
public void testAllocateMemory9() {
// memory.limit() < offset, > size
// memory.limit() < offset - size
program.initMem(ByteBuffer.allocate(64));
int offset = 96;
int size = 0;
program.allocateMemory(offset, size);
assertEquals(64, program.getMemSize());
}
/************************************************/
@Test
public void testAllocateMemory10() {
// memory = null, offset > size
int offset = 32;
int size = 0;
program.allocateMemory(offset, size);
assertEquals(0, program.getMemSize());
}
@Test
public void testAllocateMemory11() {
// memory = null, offset < size
int offset = 0;
int size = 32;
program.allocateMemory(offset, size);
assertEquals(32, program.getMemSize());
}
@Test
public void testAllocateMemory12() {
// memory.limit() < offset, < size
program.initMem(ByteBuffer.allocate(64));
int offset = 64;
int size = 96;
program.allocateMemory(offset, size);
assertEquals(160, program.getMemSize());
}
@Test
public void testAllocateMemory13() {
// memory.limit() > offset, < size
program.initMem(ByteBuffer.allocate(64));
int offset = 32;
int size = 128;
program.allocateMemory(offset, size);
assertEquals(160, program.getMemSize());
}
@Test
public void testAllocateMemory14() {
// memory.limit() < offset, == size
program.initMem(ByteBuffer.allocate(64));
int offset = 96;
int size = 64;
program.allocateMemory(offset, size);
assertEquals(160, program.getMemSize());
}
@Test
public void testAllocateMemory15() {
// memory.limit() == offset, < size
program.initMem(ByteBuffer.allocate(64));
int offset = 64;
int size = 96;
program.allocateMemory(offset, size);
assertEquals(160, program.getMemSize());
}
@Test
public void testAllocateMemory16() {
// memory.limit() == offset, == size
// memory.limit() > offset - size
program.initMem(ByteBuffer.allocate(64));
int offset = 64;
int size = 64;
program.allocateMemory(offset, size);
assertEquals(128, program.getMemSize());
}
@Test
public void testAllocateMemory17() {
// memory.limit() > offset + size
program.initMem(ByteBuffer.allocate(96));
int offset = 32;
int size = 32;
program.allocateMemory(offset, size);
assertEquals(96, program.getMemSize());
}
@Test
public void testAllocateMemoryUnrounded1() {
// memory unrounded
program.initMem(ByteBuffer.allocate(64));
int offset = 64;
int size = 32;
program.allocateMemory(offset, size);
assertEquals(96, program.getMemSize());
}
@Test
public void testAllocateMemoryUnrounded2() {
// offset unrounded
program.initMem(ByteBuffer.allocate(64));
int offset = 16;
int size = 32;
program.allocateMemory(offset, size);
assertEquals(64, program.getMemSize());
}
@Test
public void testAllocateMemoryUnrounded3() {
// size unrounded
program.initMem(ByteBuffer.allocate(64));
int offset = 64;
int size = 16;
program.allocateMemory(offset, size);
assertEquals(96, program.getMemSize());
}
@Test
public void testAllocateMemoryUnrounded4() {
// memory + offset unrounded
program.initMem(ByteBuffer.allocate(64));
int offset = 16;
int size = 32;
program.allocateMemory(offset, size);
assertEquals(64, program.getMemSize());
}
@Test
public void testAllocateMemoryUnrounded5() {
// memory + size unrounded
program.initMem(ByteBuffer.allocate(64));
int offset = 32;
int size = 16;
program.allocateMemory(offset, size);
assertEquals(64, program.getMemSize());
}
@Test
public void testAllocateMemoryUnrounded6() {
// offset + size unrounded
program.initMem(ByteBuffer.allocate(32));
int offset = 16;
int size = 16;
program.allocateMemory(offset, size);
assertEquals(32, program.getMemSize());
}
@Test
public void testAllocateMemoryUnrounded7() {
// memory + offset + size unrounded
program.initMem(ByteBuffer.allocate(32));
int offset = 16;
int size = 16;
program.allocateMemory(offset, size);
assertEquals(32, program.getMemSize());
}
@Ignore
@Test
public void testInitialInsert() {
// todo: fix the array out of bound here
int offset = 32;
int size = 00;
program.memorySave(32, 0, new byte[0]);
assertEquals(32, program.getMemSize());
}
}

View File

@ -1,659 +0,0 @@
package test.ethereum.vm;
import org.ethereum.core.AccountState;
import org.ethereum.crypto.HashUtil;
import org.ethereum.facade.Repository;
import org.ethereum.vm.DataWord;
import org.ethereum.vm.Program;
import org.ethereum.vm.ProgramInvokeMockImpl;
import org.ethereum.vm.VM;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import static org.junit.Assert.assertEquals;
/**
* @author Roman Mandeleil
* @since 16.06.2014
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class VMComplexTest {
@Test // contract call recursive
public void test1() {
/**
* #The code will run
* ------------------
a = contract.storage[999]
if a > 0:
contract.storage[999] = a - 1
# call to contract: 77045e71a7a2c50903d88e564cd72fab11e82051
send((tx.gas / 10 * 8), 0x77045e71a7a2c50903d88e564cd72fab11e82051, 0)
else:
stop
*/
int expectedGas = 436;
DataWord key1 = new DataWord(999);
DataWord value1 = new DataWord(3);
// Set contract into Database
String callerAddr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
String contractAddr = "77045e71a7a2c50903d88e564cd72fab11e82051";
String code =
"6103e75460005260006000511115630000004c576001600051036103e755600060006000600060007377045e71a7a2c50903d88e564cd72fab11e820516008600a5a0402f1630000004c00565b00";
byte[] contractAddrB = Hex.decode(contractAddr);
byte[] callerAddrB = Hex.decode(callerAddr);
byte[] codeB = Hex.decode(code);
byte[] codeKey = HashUtil.sha3(codeB);
AccountState accountState = new AccountState();
accountState.setCodeHash(codeKey);
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
pi.setOwnerAddress(contractAddrB);
Repository repository = pi.getRepository();
repository.createAccount(callerAddrB);
repository.addBalance(callerAddrB, new BigInteger("100000000000000000000"));
repository.createAccount(contractAddrB);
repository.saveCode(contractAddrB, codeB);
repository.addStorageRow(contractAddrB, key1, value1);
// Play the program
VM vm = new VM();
Program program = new Program(codeB, pi);
try {
while (!program.isStopped())
vm.step(program);
} catch (RuntimeException e) {
program.setRuntimeFailure(e);
}
System.out.println();
System.out.println("============ Results ============");
BigInteger balance = repository.getBalance(callerAddrB);
System.out.println("*** Used gas: " + program.getResult().getGasUsed());
System.out.println("*** Contract Balance: " + balance);
// todo: assert caller balance after contract exec
repository.close();
assertEquals(expectedGas, program.getResult().getGasUsed());
}
@Test // contractB call contractA with data to storage
public void test2() {
/**
* #The code will run
* ------------------
contract A: 77045e71a7a2c50903d88e564cd72fab11e82051
---------------
a = msg.data[0]
b = msg.data[1]
contract.storage[a]
contract.storage[b]
contract B: 83c5541a6c8d2dbad642f385d8d06ca9b6c731ee
-----------
a = msg((tx.gas / 10 * 8), 0x77045e71a7a2c50903d88e564cd72fab11e82051, 0, [11, 22, 33], 3, 6)
*/
long expectedVal_1 = 11;
long expectedVal_2 = 22;
// Set contract into Database
String callerAddr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
String contractA_addr = "77045e71a7a2c50903d88e564cd72fab11e82051";
String contractB_addr = "83c5541a6c8d2dbad642f385d8d06ca9b6c731ee";
String code_a = "60006020023560005260016020023560205260005160005560205160015500";
String code_b = "6000601f5360e05960e05952600060c05901536060596020015980602001600b9052806040016016905280606001602190526080905260007377045e71a7a2c50903d88e564cd72fab11e820516103e8f1602060000260a00160200151600052";
byte[] caller_addr_bytes = Hex.decode(callerAddr);
byte[] contractA_addr_bytes = Hex.decode(contractA_addr);
byte[] codeA = Hex.decode(code_a);
byte[] contractB_addr_bytes = Hex.decode(contractB_addr);
byte[] codeB = Hex.decode(code_b);
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
pi.setOwnerAddress(contractB_addr_bytes);
Repository repository = pi.getRepository();
repository.createAccount(contractA_addr_bytes);
repository.saveCode(contractA_addr_bytes, codeA);
repository.createAccount(contractB_addr_bytes);
repository.saveCode(contractB_addr_bytes, codeB);
repository.createAccount(caller_addr_bytes);
repository.addBalance(caller_addr_bytes, new BigInteger("100000000000000000000"));
// ****************** //
// Play the program //
// ****************** //
VM vm = new VM();
Program program = new Program(codeB, pi);
try {
while (!program.isStopped())
vm.step(program);
} catch (RuntimeException e) {
program.setRuntimeFailure(e);
}
System.out.println();
System.out.println("============ Results ============");
System.out.println("*** Used gas: " + program.getResult().getGasUsed());
DataWord value_1 = repository.getStorageValue(contractA_addr_bytes, new DataWord(00));
DataWord value_2 = repository.getStorageValue(contractA_addr_bytes, new DataWord(01));
repository.close();
assertEquals(expectedVal_1, value_1.longValue());
assertEquals(expectedVal_2, value_2.longValue());
// TODO: check that the value pushed after exec is 1
}
@Ignore
@Test // contractB call contractA with return expectation
public void test3() {
/**
* #The code will run
* ------------------
contract A: 77045e71a7a2c50903d88e564cd72fab11e82051
---------------
a = 11
b = 22
c = 33
d = 44
e = 55
f = 66
[asm 192 0 RETURN asm]
contract B: 83c5541a6c8d2dbad642f385d8d06ca9b6c731ee
-----------
a = msg((tx.gas / 10 * 8), 0x77045e71a7a2c50903d88e564cd72fab11e82051, 0, [11, 22, 33], 3, 6)
*/
long expectedVal_1 = 11;
long expectedVal_2 = 22;
long expectedVal_3 = 33;
long expectedVal_4 = 44;
long expectedVal_5 = 55;
long expectedVal_6 = 66;
// Set contract into Database
byte[] caller_addr_bytes = Hex.decode("cd2a3d9f938e13cd947ec05abc7fe734df8dd826");
byte[] contractA_addr_bytes = Hex.decode("77045e71a7a2c50903d88e564cd72fab11e82051");
byte[] contractB_addr_bytes = Hex.decode("83c5541a6c8d2dbad642f385d8d06ca9b6c731ee");
byte[] codeA = Hex.decode("600b60005260166020526021604052602c6060526037608052604260a05260c06000f2");
byte[] codeB = Hex.decode("6000601f5360e05960e05952600060c05901536060596020015980602001600b9052806040016016905280606001602190526080905260007377045e71a7a2c50903d88e564cd72fab11e820516103e8f1602060000260a00160200151600052");
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
pi.setOwnerAddress(contractB_addr_bytes);
Repository repository = pi.getRepository();
repository.createAccount(contractA_addr_bytes);
repository.saveCode(contractA_addr_bytes, codeA);
repository.createAccount(contractB_addr_bytes);
repository.saveCode(contractB_addr_bytes, codeB);
repository.createAccount(caller_addr_bytes);
repository.addBalance(caller_addr_bytes, new BigInteger("100000000000000000000"));
// ****************** //
// Play the program //
// ****************** //
VM vm = new VM();
Program program = new Program(codeB, pi);
try {
while (!program.isStopped())
vm.step(program);
} catch (RuntimeException e) {
program.setRuntimeFailure(e);
}
System.out.println();
System.out.println("============ Results ============");
System.out.println("*** Used gas: " + program.getResult().getGasUsed());
DataWord value1 = program.memoryLoad(new DataWord(32));
DataWord value2 = program.memoryLoad(new DataWord(64));
DataWord value3 = program.memoryLoad(new DataWord(96));
DataWord value4 = program.memoryLoad(new DataWord(128));
DataWord value5 = program.memoryLoad(new DataWord(160));
DataWord value6 = program.memoryLoad(new DataWord(192));
repository.close();
assertEquals(expectedVal_1, value1.longValue());
assertEquals(expectedVal_2, value2.longValue());
assertEquals(expectedVal_3, value3.longValue());
assertEquals(expectedVal_4, value4.longValue());
assertEquals(expectedVal_5, value5.longValue());
assertEquals(expectedVal_6, value6.longValue());
// TODO: check that the value pushed after exec is 1
}
@Test // CREATE magic
public void test4() {
/**
* #The code will run
* ------------------
contract A: 77045e71a7a2c50903d88e564cd72fab11e82051
-----------
a = 0x7f60c860005461012c6020540000000000000000000000000000000000000000
b = 0x0060005460206000f20000000000000000000000000000000000000000000000
create(100, 0 41)
contract B: (the contract to be created the addr will be defined to: 8e45367623a2865132d9bf875d5cfa31b9a0cd94)
-----------
a = 200
b = 300
*/
// Set contract into Database
byte[] caller_addr_bytes = Hex.decode("cd2a3d9f938e13cd947ec05abc7fe734df8dd826");
byte[] contractA_addr_bytes = Hex.decode("77045e71a7a2c50903d88e564cd72fab11e82051");
byte[] codeA = Hex.decode("7f7f60c860005461012c602054000000000000" +
"00000000000000000000000000006000547e60" +
"005460206000f2000000000000000000000000" +
"0000000000000000000000602054602960006064f0");
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
pi.setOwnerAddress(contractA_addr_bytes);
Repository repository = pi.getRepository();
repository.createAccount(contractA_addr_bytes);
repository.saveCode(contractA_addr_bytes, codeA);
repository.createAccount(caller_addr_bytes);
// ****************** //
// Play the program //
// ****************** //
VM vm = new VM();
Program program = new Program(codeA, pi);
try {
while (!program.isStopped())
vm.step(program);
} catch (RuntimeException e) {
program.setRuntimeFailure(e);
}
System.out.println();
System.out.println("============ Results ============");
System.out.println("*** Used gas: " + program.getResult().getGasUsed());
// TODO: check that the value pushed after exec is the new address
repository.close();
}
@Test // CALL contract with too much gas
@Ignore
public void test5() {
// TODO CALL contract with gas > gasRemaining && gas > Long.MAX_VALUE
}
@Ignore
@Test // contractB call itself with code from contractA
public void test6() {
/**
* #The code will run
* ------------------
contract A: 945304eb96065b2a98b57a48a06ae28d285a71b5
---------------
PUSH1 0 CALLDATALOAD SLOAD NOT PUSH1 9 JUMPI STOP
PUSH1 32 CALLDATALOAD PUSH1 0 CALLDATALOAD SSTORE
contract B: 0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6
-----------
{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
(MSTORE 32 0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa)
[[ 0 ]] (CALLSTATELESS 1000000 0x945304eb96065b2a98b57a48a06ae28d285a71b5 23 0 64 64 0)
}
*/
// Set contract into Database
byte[] caller_addr_bytes = Hex.decode("cd1722f3947def4cf144679da39c4c32bdc35681");
byte[] contractA_addr_bytes = Hex.decode("945304eb96065b2a98b57a48a06ae28d285a71b5");
byte[] contractB_addr_bytes = Hex.decode("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6");
byte[] codeA = Hex.decode("60003554156009570060203560003555");
byte[] codeB = Hex.decode("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000527faaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa6020526000604060406000601773945304eb96065b2a98b57a48a06ae28d285a71b5620f4240f3600055");
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
pi.setOwnerAddress(contractB_addr_bytes);
pi.setGasLimit(10000000000000l);
Repository repository = pi.getRepository();
repository.createAccount(contractA_addr_bytes);
repository.saveCode(contractA_addr_bytes, codeA);
repository.addBalance(contractA_addr_bytes, BigInteger.valueOf(23));
repository.createAccount(contractB_addr_bytes);
repository.saveCode(contractB_addr_bytes, codeB);
repository.addBalance(contractB_addr_bytes, new BigInteger("1000000000000000000"));
repository.createAccount(caller_addr_bytes);
repository.addBalance(caller_addr_bytes, new BigInteger("100000000000000000000"));
// ****************** //
// Play the program //
// ****************** //
VM vm = new VM();
Program program = new Program(codeB, pi);
try {
while (!program.isStopped())
vm.step(program);
} catch (RuntimeException e) {
program.setRuntimeFailure(e);
}
System.out.println();
System.out.println("============ Results ============");
System.out.println("*** Used gas: " + program.getResult().getGasUsed());
DataWord memValue1 = program.memoryLoad(new DataWord(0));
DataWord memValue2 = program.memoryLoad(new DataWord(32));
DataWord storeValue1 = repository.getStorageValue(contractB_addr_bytes, new DataWord(00));
repository.close();
assertEquals("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", memValue1.toString());
assertEquals("aaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa", memValue2.toString());
assertEquals("0x1", storeValue1.shortHex());
// TODO: check that the value pushed after exec is 1
}
//sha3_memSizeQuadraticCost33
@Test // contract call quadratic memory use
public void test7() {
int expectedGas = 357;
DataWord key1 = new DataWord(999);
DataWord value1 = new DataWord(3);
// Set contract into Database
String callerAddr = "cd1722f3947def4cf144679da39c4c32bdc35681";
String contractAddr = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6";
String code = "600161040020600055";
byte[] contractAddrB = Hex.decode(contractAddr);
byte[] callerAddrB = Hex.decode(callerAddr);
byte[] codeB = Hex.decode(code);
byte[] codeKey = HashUtil.sha3(codeB);
AccountState accountState = new AccountState();
accountState.setCodeHash(codeKey);
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
pi.setOwnerAddress(contractAddrB);
Repository repository = pi.getRepository();
repository.createAccount(callerAddrB);
repository.addBalance(callerAddrB, new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639935"));
repository.createAccount(contractAddrB);
repository.saveCode(contractAddrB, codeB);
repository.addStorageRow(contractAddrB, key1, value1);
// Play the program
VM vm = new VM();
Program program = new Program(codeB, pi);
try {
while (!program.isStopped())
vm.step(program);
} catch (RuntimeException e) {
program.setRuntimeFailure(e);
}
System.out.println();
System.out.println("============ Results ============");
BigInteger balance = repository.getBalance(callerAddrB);
System.out.println("*** Used gas: " + program.getResult().getGasUsed());
System.out.println("*** Contract Balance: " + balance);
// todo: assert caller balance after contract exec
repository.close();
assertEquals(expectedGas, program.getResult().getGasUsed());
}
//sha3_memSizeQuadraticCost31
@Test // contract call quadratic memory use
public void test8() {
int expectedGas = 354;
DataWord key1 = new DataWord(999);
DataWord value1 = new DataWord(3);
// Set contract into Database
String callerAddr = "cd1722f3947def4cf144679da39c4c32bdc35681";
String contractAddr = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6";
String code = "60016103c020600055";
byte[] contractAddrB = Hex.decode(contractAddr);
byte[] callerAddrB = Hex.decode(callerAddr);
byte[] codeB = Hex.decode(code);
byte[] codeKey = HashUtil.sha3(codeB);
AccountState accountState = new AccountState();
accountState.setCodeHash(codeKey);
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
pi.setOwnerAddress(contractAddrB);
Repository repository = pi.getRepository();
repository.createAccount(callerAddrB);
repository.addBalance(callerAddrB, new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639935"));
repository.createAccount(contractAddrB);
repository.saveCode(contractAddrB, codeB);
repository.addStorageRow(contractAddrB, key1, value1);
// Play the program
VM vm = new VM();
Program program = new Program(codeB, pi);
try {
while (!program.isStopped())
vm.step(program);
} catch (RuntimeException e) {
program.setRuntimeFailure(e);
}
System.out.println();
System.out.println("============ Results ============");
BigInteger balance = repository.getBalance(callerAddrB);
System.out.println("*** Used gas: " + program.getResult().getGasUsed());
System.out.println("*** Contract Balance: " + balance);
// todo: assert caller balance after contract exec
repository.close();
assertEquals(expectedGas, program.getResult().getGasUsed());
}
//sha3_memSizeQuadraticCost32
@Test // contract call quadratic memory use
public void test9() {
int expectedGas = 356;
DataWord key1 = new DataWord(9999);
DataWord value1 = new DataWord(3);
// Set contract into Database
String callerAddr = "cd1722f3947def4cf144679da39c4c32bdc35681";
String contractAddr = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6";
String code = "60016103e020600055";
byte[] contractAddrB = Hex.decode(contractAddr);
byte[] callerAddrB = Hex.decode(callerAddr);
byte[] codeB = Hex.decode(code);
byte[] codeKey = HashUtil.sha3(codeB);
AccountState accountState = new AccountState();
accountState.setCodeHash(codeKey);
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
pi.setOwnerAddress(contractAddrB);
Repository repository = pi.getRepository();
repository.createAccount(callerAddrB);
repository.addBalance(callerAddrB, new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639935"));
repository.createAccount(contractAddrB);
repository.saveCode(contractAddrB, codeB);
repository.addStorageRow(contractAddrB, key1, value1);
// Play the program
VM vm = new VM();
Program program = new Program(codeB, pi);
try {
while (!program.isStopped())
vm.step(program);
} catch (RuntimeException e) {
program.setRuntimeFailure(e);
}
System.out.println();
System.out.println("============ Results ============");
BigInteger balance = repository.getBalance(callerAddrB);
System.out.println("*** Used gas: " + program.getResult().getGasUsed());
System.out.println("*** Contract Balance: " + balance);
// todo: assert caller balance after contract exec
repository.close();
assertEquals(expectedGas, program.getResult().getGasUsed());
}
//sha3_memSizeQuadraticCost32_zeroSize
@Test // contract call quadratic memory use
public void test10() {
int expectedGas = 313;
DataWord key1 = new DataWord(999);
DataWord value1 = new DataWord(3);
// Set contract into Database
String callerAddr = "cd1722f3947def4cf144679da39c4c32bdc35681";
String contractAddr = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6";
String code = "600061040020600055";
byte[] contractAddrB = Hex.decode(contractAddr);
byte[] callerAddrB = Hex.decode(callerAddr);
byte[] codeB = Hex.decode(code);
byte[] codeKey = HashUtil.sha3(codeB);
AccountState accountState = new AccountState();
accountState.setCodeHash(codeKey);
ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl();
pi.setOwnerAddress(contractAddrB);
Repository repository = pi.getRepository();
repository.createAccount(callerAddrB);
repository.addBalance(callerAddrB, new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639935"));
repository.createAccount(contractAddrB);
repository.saveCode(contractAddrB, codeB);
repository.addStorageRow(contractAddrB, key1, value1);
// Play the program
VM vm = new VM();
Program program = new Program(codeB, pi);
try {
while (!program.isStopped())
vm.step(program);
} catch (RuntimeException e) {
program.setRuntimeFailure(e);
}
System.out.println();
System.out.println("============ Results ============");
BigInteger balance = repository.getBalance(callerAddrB);
System.out.println("*** Used gas: " + program.getResult().getGasUsed());
System.out.println("*** Contract Balance: " + balance);
// todo: assert caller balance after contract exec
repository.close();
assertEquals(expectedGas, program.getResult().getGasUsed());
}
}

View File

@ -1,566 +0,0 @@
package test.ethereum.vm;
import org.ethereum.vm.DataWord;
import org.ethereum.vm.Program;
import org.ethereum.vm.Program.OutOfGasException;
import org.ethereum.vm.Program.StackTooSmallException;
import org.ethereum.vm.ProgramInvokeMockImpl;
import org.ethereum.vm.VM;
import org.junit.After;
import org.junit.Before;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import static org.junit.Assert.*;
/**
* @author Roman Mandeleil
* @since 01.06.2014
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class VMCustomTest {
private ProgramInvokeMockImpl invoke;
private Program program;
@Before
public void setup() {
byte[] ownerAddress = Hex.decode("77045E71A7A2C50903D88E564CD72FAB11E82051");
byte[] msgData = Hex.decode("00000000000000000000000000000000000000000000000000000000000000A1" +
"00000000000000000000000000000000000000000000000000000000000000B1");
invoke = new ProgramInvokeMockImpl(msgData);
invoke.setOwnerAddress(ownerAddress);
invoke.getRepository().createAccount(ownerAddress);
invoke.getRepository().addBalance(ownerAddress, BigInteger.valueOf(1000L));
}
@After
public void tearDown() {
invoke.getRepository().close();
}
@Test // CALLDATASIZE OP
public void testCALLDATASIZE_1() {
VM vm = new VM();
program = new Program(Hex.decode("36"), invoke);
String s_expected_1 = "0000000000000000000000000000000000000000000000000000000000000040";
vm.step(program);
DataWord item1 = program.stackPop();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // CALLDATALOAD OP
public void testCALLDATALOAD_1() {
VM vm = new VM();
program =
new Program(Hex.decode("600035"), invoke);
String s_expected_1 = "00000000000000000000000000000000000000000000000000000000000000A1";
vm.step(program);
vm.step(program);
DataWord item1 = program.stackPop();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // CALLDATALOAD OP
public void testCALLDATALOAD_2() {
VM vm = new VM();
program =
new Program(Hex.decode("600235"), invoke);
String s_expected_1 = "0000000000000000000000000000000000000000000000000000000000A10000";
vm.step(program);
vm.step(program);
DataWord item1 = program.stackPop();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // CALLDATALOAD OP
public void testCALLDATALOAD_3() {
VM vm = new VM();
program =
new Program(Hex.decode("602035"), invoke);
String s_expected_1 = "00000000000000000000000000000000000000000000000000000000000000B1";
vm.step(program);
vm.step(program);
DataWord item1 = program.stackPop();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // CALLDATALOAD OP
public void testCALLDATALOAD_4() {
VM vm = new VM();
program =
new Program(Hex.decode("602335"), invoke);
String s_expected_1 = "00000000000000000000000000000000000000000000000000000000B1000000";
vm.step(program);
vm.step(program);
DataWord item1 = program.stackPop();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // CALLDATALOAD OP
public void testCALLDATALOAD_5() {
VM vm = new VM();
program =
new Program(Hex.decode("603F35"), invoke);
String s_expected_1 = "B100000000000000000000000000000000000000000000000000000000000000";
vm.step(program);
vm.step(program);
DataWord item1 = program.stackPop();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test(expected = RuntimeException.class) // CALLDATALOAD OP mal
public void testCALLDATALOAD_6() {
VM vm = new VM();
program =
new Program(Hex.decode("35"), invoke);
try {
vm.step(program);
} finally {
assertTrue(program.isStopped());
}
}
@Test // CALLDATACOPY OP
public void testCALLDATACOPY_1() {
VM vm = new VM();
program =
new Program(Hex.decode("60206000600037"), invoke);
String m_expected = "00000000000000000000000000000000000000000000000000000000000000A1";
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
assertEquals(m_expected, Hex.toHexString(program.getMemory().array()).toUpperCase());
}
@Test // CALLDATACOPY OP
public void testCALLDATACOPY_2() {
VM vm = new VM();
program =
new Program(Hex.decode("60406000600037"), invoke);
String m_expected = "00000000000000000000000000000000000000000000000000000000000000A1" +
"00000000000000000000000000000000000000000000000000000000000000B1";
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
assertEquals(m_expected, Hex.toHexString(program.getMemory().array()).toUpperCase());
}
@Test // CALLDATACOPY OP
public void testCALLDATACOPY_3() {
VM vm = new VM();
program =
new Program(Hex.decode("60406004600037"), invoke);
String m_expected = "000000000000000000000000000000000000000000000000000000A100000000" +
"000000000000000000000000000000000000000000000000000000B100000000";
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
assertEquals(m_expected, Hex.toHexString(program.getMemory().array()).toUpperCase());
}
@Test // CALLDATACOPY OP
public void testCALLDATACOPY_4() {
VM vm = new VM();
program =
new Program(Hex.decode("60406000600437"), invoke);
String m_expected = "0000000000000000000000000000000000000000000000000000000000000000" +
"000000A100000000000000000000000000000000000000000000000000000000" +
"000000B100000000000000000000000000000000000000000000000000000000";
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
assertEquals(m_expected, Hex.toHexString(program.getMemory().array()).toUpperCase());
}
@Test // CALLDATACOPY OP
public void testCALLDATACOPY_5() {
VM vm = new VM();
program =
new Program(Hex.decode("60406000600437"), invoke);
String m_expected = "0000000000000000000000000000000000000000000000000000000000000000" +
"000000A100000000000000000000000000000000000000000000000000000000" +
"000000B100000000000000000000000000000000000000000000000000000000";
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
assertEquals(m_expected, Hex.toHexString(program.getMemory().array()).toUpperCase());
}
@Test(expected = StackTooSmallException.class) // CALLDATACOPY OP mal
public void testCALLDATACOPY_6() {
VM vm = new VM();
program =
new Program(Hex.decode("6040600037"), invoke);
try {
vm.step(program);
vm.step(program);
vm.step(program);
} finally {
assertTrue(program.isStopped());
}
}
@Test(expected = OutOfGasException.class) // CALLDATACOPY OP mal
public void testCALLDATACOPY_7() {
VM vm = new VM();
program =
new Program(Hex.decode("6020600073CC0929EB16730E7C14FEFC63006AC2D794C5795637"), invoke);
try {
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
} finally {
assertTrue(program.isStopped());
}
}
@Test // ADDRESS OP
public void testADDRESS_1() {
VM vm = new VM();
program = new Program(Hex.decode("30"), invoke);
String s_expected_1 = "00000000000000000000000077045E71A7A2C50903D88E564CD72FAB11E82051";
vm.step(program);
DataWord item1 = program.stackPop();
program.getResult().getRepository().close();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // BALANCE OP
public void testBALANCE_1() {
VM vm = new VM();
program =
new Program(Hex.decode("3031"), invoke);
String s_expected_1 = "00000000000000000000000000000000000000000000000000000000000003E8";
vm.step(program);
vm.step(program);
DataWord item1 = program.stackPop();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // ORIGIN OP
public void testORIGIN_1() {
VM vm = new VM();
program =
new Program(Hex.decode("32"), invoke);
String s_expected_1 = "00000000000000000000000013978AEE95F38490E9769C39B2773ED763D9CD5F";
vm.step(program);
DataWord item1 = program.stackPop();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // CALLER OP
public void testCALLER_1() {
VM vm = new VM();
program =
new Program(Hex.decode("33"), invoke);
String s_expected_1 = "000000000000000000000000885F93EED577F2FC341EBB9A5C9B2CE4465D96C4";
vm.step(program);
DataWord item1 = program.stackPop();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // CALLVALUE OP
public void testCALLVALUE_1() {
VM vm = new VM();
program =
new Program(Hex.decode("34"), invoke);
String s_expected_1 = "0000000000000000000000000000000000000000000000000DE0B6B3A7640000";
vm.step(program);
DataWord item1 = program.stackPop();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // SHA3 OP
public void testSHA3_1() {
VM vm = new VM();
program =
new Program(Hex.decode("60016000536001600020"), invoke);
String s_expected_1 = "5FE7F977E71DBA2EA1A68E21057BEEBB9BE2AC30C6410AA38D4F3FBE41DCFFD2";
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
DataWord item1 = program.stackPop();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // SHA3 OP
public void testSHA3_2() {
VM vm = new VM();
program =
new Program(Hex.decode("6102016000526002601E20"), invoke);
String s_expected_1 = "114A3FE82A0219FCC31ABD15617966A125F12B0FD3409105FC83B487A9D82DE4";
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
DataWord item1 = program.stackPop();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test(expected = StackTooSmallException.class) // SHA3 OP mal
public void testSHA3_3() {
VM vm = new VM();
program =
new Program(Hex.decode("610201600052600220"), invoke);
try {
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
vm.step(program);
} finally {
assertTrue(program.isStopped());
}
}
@Test // BLOCKHASH OP
public void testBLOCKHASH_1() {
VM vm = new VM();
program =
new Program(Hex.decode("600140"), invoke);
String s_expected_1 = "C89EFDAA54C0F20C7ADF612882DF0950F5A951637E0307CDCB4C672F298B8BC6";
vm.step(program);
vm.step(program);
DataWord item1 = program.stackPop();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // COINBASE OP
public void testCOINBASE_1() {
VM vm = new VM();
program =
new Program(Hex.decode("41"), invoke);
String s_expected_1 = "000000000000000000000000E559DE5527492BCB42EC68D07DF0742A98EC3F1E";
vm.step(program);
DataWord item1 = program.stackPop();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // TIMESTAMP OP
public void testTIMESTAMP_1() {
VM vm = new VM();
program =
new Program(Hex.decode("42"), invoke);
String s_expected_1 = "000000000000000000000000000000000000000000000000000000005387FE24";
vm.step(program);
DataWord item1 = program.stackPop();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // NUMBER OP
public void testNUMBER_1() {
VM vm = new VM();
program =
new Program(Hex.decode("43"), invoke);
String s_expected_1 = "0000000000000000000000000000000000000000000000000000000000000021";
vm.step(program);
DataWord item1 = program.stackPop();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // DIFFICULTY OP
public void testDIFFICULTY_1() {
VM vm = new VM();
program =
new Program(Hex.decode("44"), invoke);
String s_expected_1 = "00000000000000000000000000000000000000000000000000000000003ED290";
vm.step(program);
DataWord item1 = program.stackPop();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // GASPRICE OP
public void testGASPRICE_1() {
VM vm = new VM();
program =
new Program(Hex.decode("3A"), invoke);
String s_expected_1 = "000000000000000000000000000000000000000000000000000009184E72A000";
vm.step(program);
DataWord item1 = program.stackPop();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // GAS OP
public void testGAS_1() {
VM vm = new VM();
program =
new Program(Hex.decode("5A"), invoke);
String s_expected_1 = "00000000000000000000000000000000000000000000000000000000000F423F";
vm.step(program);
DataWord item1 = program.stackPop();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test // GASLIMIT OP
public void testGASLIMIT_1() {
VM vm = new VM();
program =
new Program(Hex.decode("45"), invoke);
String s_expected_1 = "00000000000000000000000000000000000000000000000000000000000F4240";
vm.step(program);
DataWord item1 = program.stackPop();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
@Test(expected = Program.IllegalOperationException.class) // INVALID OP
public void testINVALID_1() {
VM vm = new VM();
program = new Program(Hex.decode("60012F6002"), invoke);
String s_expected_1 = "0000000000000000000000000000000000000000000000000000000000000001";
try {
vm.step(program);
vm.step(program);
} finally {
assertTrue(program.isStopped());
DataWord item1 = program.stackPop();
assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase());
}
}
/* TEST CASE LIST END */
}
// TODO: add gas expeted and calculated to all test cases
// TODO: considering: G_TXDATA + G_TRANSACTION
/**
* TODO:
*
* 22) CREATE:
* 23) CALL:
*
*
**/
/**
contract creation (gas usage)
-----------------------------
G_TRANSACTION = (500)
60016000546006601160003960066000f261778e600054 (115)
PUSH1 6001 (1)
PUSH1 6000 (1)
MSTORE 54 (1 + 1)
PUSH1 6006 (1)
PUSH1 6011 (1)
PUSH1 6000 (1)
CODECOPY 39 (1)
PUSH1 6006 (1)
PUSH1 6000 (1)
RETURN f2 (1)
61778e600054
*/

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +0,0 @@
f8f3f8efa0955f36d073ccb026b78ab3424c15cf966a7563aa270413859f78702b9e8e22cba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000180830f42408086014999e9d97480a0000000000000000000000000000000000000000000000000000000000000123dc0c0
f8f3f8efa0c1ffb0686aa17fcb5eef4137d0ae94a6db2a4fb44d4442896e5b1ac0127d52b0a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000280830f42408086014999e9dc7580a00000000000000000000000000000000000000000000000000000000000010d23c0c0
f8f3f8efa0585afbf84ec4cae31c877036b7faaacf8f5382d58e62f7acf4e5fb4b4443a62ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000380830f42408086014999e9eb0680a0000000000000000000000000000000000000000000000000000000000000866cc0c0
f8f3f8efa059df515807c95e850ff827173f5a15f25268428a3bb059a284003b018a199651a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000480830f42408086014999e9f34380a000000000000000000000000000000000000000000000000000000000000087eac0c0
f8f3f8efa0e649b61c1f19780dc5d92b32f12d2dfbabe115171d5e16e66b8e59bb386066b8a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000580830f42408086014999e9fb9380a00000000000000000000000000000000000000000000000000000000000034334c0c0
f8f3f8efa003cdbb1f1b57448cec20b10e10d0b388351e92c0905643e3b5b7151faa9901b4a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000680830f42408086014999ea24a280a000000000000000000000000000000000000000000000000000000000000031a1c0c0
f8f3f8efa03054b6cf6680d90dd88a5f73f2a15aa6ca44cbbaf8d884f3bc76846819afbd29a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000780830f42408086014999ea28e980a0000000000000000000000000000000000000000000000000000000000001c02ec0c0
f8f3f8efa03054b6cf6680d90dd88a5f73f2a15aa6ca44cbbaf8d884f3bc76846819afbd29a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000780830f42408086014999ea28ef80a0000000000000000000000000000000000000000000000000000000000001cef4c0c0
f8f3f8efa042410afa693dd995244aec75ba66cb5696327c1081ce3deba1786833d4ef7cb6a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000880830f42408086014999ea3fca80a00000000000000000000000000000000000000000000000000000000000003925c0c0
f901e5f8efa02e75ea5ffd484e286ec364e8a4241d7ced28d87ae032ec049606e756cf1a3f2ba09f17fc4194346b7510c2ce86dc7530bb25696a1f500b9b8f8e712fccba716c6e94f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000980830f42408086014999ea446d80a00000000000000000000000000000000000000000000000000000000000008cd1c0f8f1f8efa03054b6cf6680d90dd88a5f73f2a15aa6ca44cbbaf8d884f3bc76846819afbd29a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000780830f42408086014999ea28ef80a0000000000000000000000000000000000000000000000000000000000001cef4
f8f3f8efa047908cfc665cad1c70fc5d829ab96649c0519588020152c3f217cbe18ac3ab8ba09f17fc4194346b7510c2ce86dc7530bb25696a1f500b9b8f8e712fccba716c6e94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000a80830f42408086014999ea4cee80a0000000000000000000000000000000000000000000000000000000000000a9fbc0c0
f8f3f8efa0613cdcce701b646c35f2fd23df535363df98a610036a3e4fec5809a444adc47da09f17fc4194346b7510c2ce86dc7530bb25696a1f500b9b8f8e712fccba716c6e94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000b80830f42408086014999ea56d080a0000000000000000000000000000000000000000000000000000000000000533fc0c0
f901e5f8efa0809b9f2368ab54f8a656ad43a1d11579cd908ef64dcb1756cb44251a2bd8b878a0d7987a94b8e13555797d283bcf98805d1173908b25c7e0f43e7dd20387dc1ac5942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000880830f42408086014999ea408780a0000000000000000000000000000000000000000000000000000000000002c1b5c0f8f1f8efa03054b6cf6680d90dd88a5f73f2a15aa6ca44cbbaf8d884f3bc76846819afbd29a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000780830f42408086014999ea28e980a0000000000000000000000000000000000000000000000000000000000001c02e
f8f3f8efa064b6b7ba2f2f2e14b72152fc80774b686d4e08638d85aa4c55ebd8679c81fa0aa0d7987a94b8e13555797d283bcf98805d1173908b25c7e0f43e7dd20387dc1ac5942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000980830f42408086014999ea635780a00000000000000000000000000000000000000000000000000000000000032023c0c0
f8f3f8efa00ae67dc8275cbae12d9168ed886e8175583d915953fb16f83ae4aea0df4f8f5fa0d7987a94b8e13555797d283bcf98805d1173908b25c7e0f43e7dd20387dc1ac5942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000a80830f42408086014999ea8ab180a0000000000000000000000000000000000000000000000000000000000000b4ccc0c0
f8f3f8efa06cf2e0657188fa80869d998d97079fe435a176576a312efab6cc5731d8e8cc34a09f17fc4194346b7510c2ce86dc7530bb25696a1f500b9b8f8e712fccba716c6e94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000c80830f42408086014999ea5cab80a0000000000000000000000000000000000000000000000000000000000005448ac0c0
f8f3f8efa0a3b0d1d3d330f427a51aeb734d038dc4b099425b4b580c70cc32ccad48a5b813a0d7987a94b8e13555797d283bcf98805d1173908b25c7e0f43e7dd20387dc1ac5942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000b80830f42408086014999ea951080a00000000000000000000000000000000000000000000000000000000000027a21c0c0
f8f3f8efa04ac8224ab83845571ae84f2e45966798a56013d7d880f9e6bd7fd93cc565ab54a0d7987a94b8e13555797d283bcf98805d1173908b25c7e0f43e7dd20387dc1ac5942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000c80830f42408086014999eab48780a00000000000000000000000000000000000000000000000000000000000000e45c0c0
f8f3f8efa02df9a3b43b2c2adea2dd4dac12fcf26b2121c784a1511f155b26aad7456e7014a09f17fc4194346b7510c2ce86dc7530bb25696a1f500b9b8f8e712fccba716c6e94f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000d80830f42408086014999ea9da280a0000000000000000000000000000000000000000000000000000000000002608ac0c0
f8f3f8efa055155c72460fe0128ca834acc122aec3363143f629876a832268c9885c8ef03fa09f17fc4194346b7510c2ce86dc7530bb25696a1f500b9b8f8e712fccba716c6e94f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000e80830f42408086014999eabbee80a000000000000000000000000000000000000000000000000000000000000049f6c0c0
f8f3f8efa0d64cc441d61c26f2c701ff70fa26eb16aa1f48885ea50a6f020282ae0924657da09f17fc4194346b7510c2ce86dc7530bb25696a1f500b9b8f8e712fccba716c6e94f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000f80830f42408086014999eac15780a000000000000000000000000000000000000000000000000000000000000095c8c0c0
f8f3f8efa00e1f706d15e634e980d072ae00679e635827bafad2afec5ac882901105e62e4da09f17fc4194346b7510c2ce86dc7530bb25696a1f500b9b8f8e712fccba716c6e94f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001080830f42408086014999eaca4080a00000000000000000000000000000000000000000000000000000000000009219c0c0
f8f3f8efa072bc570d5ed554c86c9ac2ac9ffb0ab5b23c234cabdb97f0fb868fb3290e2802a09f17fc4194346b7510c2ce86dc7530bb25696a1f500b9b8f8e712fccba716c6e94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001180830f42408086014999ead30480a0000000000000000000000000000000000000000000000000000000000000641dc0c0
f8f3f8efa0fb70904fbcf51a937977b97b0bc2d3a642397f3b5c734a13411e6d6c0d88acd4a09f17fc4194346b7510c2ce86dc7530bb25696a1f500b9b8f8e712fccba716c6e94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001280830f42408086014999ead9a680a00000000000000000000000000000000000000000000000000000000000002e6cc0c0
f8f3f8efa099d310c72ef9da40d6789bf5ce5d3622a45b648a71f552558f72d4dda9176ac9a09f17fc4194346b7510c2ce86dc7530bb25696a1f500b9b8f8e712fccba716c6e94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001380830f42408086014999eaddbf80a000000000000000000000000000000000000000000000000000000000000033d7c0c0
f8f3f8efa0d0b7ccbeebb92b0c65c05d3343c8b9311e3f592260b6e7a694fd615e29256c67a0d7987a94b8e13555797d283bcf98805d1173908b25c7e0f43e7dd20387dc1ac5942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000d80830f42408086014999eab72680a0000000000000000000000000000000000000000000000000000000000006567dc0c0
f8f3f8efa0e8353ae9a7e93a4f82e89d4753db5df26e700d2c1bbfe88e32cdf3e96e006a78a0d7987a94b8e13555797d283bcf98805d1173908b25c7e0f43e7dd20387dc1ac5942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000e80830f42408086014999eb04b680a0000000000000000000000000000000000000000000000000000000000000fd60c0c0
f8f3f8efa07a78a9fbfcad4a3c9b6a8d01dcccf134d79e3a2a1e1e3b09e9206b3f5eaa99e6a0d7987a94b8e13555797d283bcf98805d1173908b25c7e0f43e7dd20387dc1ac5942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000f80830f42408086014999eb126c80a00000000000000000000000000000000000000000000000000000000000016c8dc0c0
f8f3f8efa01f4d21e107c4ea7b2e6bfdcc93204d683f1eb64902b632e123a3870173a52620a0d7987a94b8e13555797d283bcf98805d1173908b25c7e0f43e7dd20387dc1ac5942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001080830f42408086014999eb255580a0000000000000000000000000000000000000000000000000000000000000a16fc0c0
f8f3f8efa0e6c6de2e8980766f5f905644d53ff8fd0fe035eb7ed6d0c448af3a1728ea0041a0d7987a94b8e13555797d283bcf98805d1173908b25c7e0f43e7dd20387dc1ac5942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001180830f42408086014999eb2ec580a0000000000000000000000000000000000000000000000000000000000000c875c0c0
f8f3f8efa0c9387dc32fc8c5ee627d919f0eb22cf5b09ca8efc453343354f1fd70c1695d68a0d7987a94b8e13555797d283bcf98805d1173908b25c7e0f43e7dd20387dc1ac5942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001280830f42408086014999eb3a0480a00000000000000000000000000000000000000000000000000000000000059e2cc0c0
f8f3f8efa0edf6ea2a3e43a59f7751f4339dc8b1beb918edb93cc7f911dc6ccddf857b1443a0d7987a94b8e13555797d283bcf98805d1173908b25c7e0f43e7dd20387dc1ac5942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001380830f42408086014999eb7eb580a0000000000000000000000000000000000000000000000000000000000003d0e2c0c0

View File

@ -1,277 +0,0 @@
f8f3f8efa0955f36d073ccb026b78ab3424c15cf966a7563aa270413859f78702b9e8e22cba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000180830f4240808601499be910b280a0000000000000000000000000000000000000000000000000000000000000e68ac0c0
f8f3f8efa094036a1ec5e8dcea7a65d3dfa3dce9c25e3dc0b5ff539b750271c95a51c5732ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000280830f4240808601499be91db080a00000000000000000000000000000000000000000000000000000000000005975c0c0
f8f3f8efa074f0ef6330f7f51766b5e3d45acbbeeadab5dcc17d6bd75f7dc4b1d58ccbdfe9a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000380830f4240808601499be923da80a0000000000000000000000000000000000000000000000000000000000000d17fc0c0
f8f3f8efa035e613fdc4913b908486569959e9d4c7bc4d1cb98d39e6c03556fd92878209c4a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000480830f4240808601499be92fb680a0000000000000000000000000000000000000000000000000000000000000052ec0c0
f8f3f8efa04f3295a098c51bfe95ec017d4ee6206728eb230d90a3ee00e5328ceec8018a11a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000580830f4240808601499be931eb80a000000000000000000000000000000000000000000000000000000000000051ddc0c0
f8f3f8efa01ef1019ed8ffca1d46b5a30b60ac1d890173725e8f3a08f1f2b2436fe5ed67aea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000680830f4240808601499be937a880a0000000000000000000000000000000000000000000000000000000000000fbbfc0c0
f8f3f8efa0ae9448de848b702908d937f87a458f2ce60ef83b99c9612b085182d2b3251289a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000780830f4240808601499be9458980a00000000000000000000000000000000000000000000000000000000000003a1ac0c0
f8f3f8efa0ae9448de848b702908d937f87a458f2ce60ef83b99c9612b085182d2b3251289a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000780830f4240808601499be9458880a00000000000000000000000000000000000000000000000000000000000003e31c0c0
f8f3f8efa01927c55d9d947312c0c00b0996f2f3fe43b741f1161d41c647efdea4673df519a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000880830f4240808601499be94a3880a00000000000000000000000000000000000000000000000000000000000003439c0c0
f901e5f8efa0bfce59e8b4532069312a5cfdc065b8af5692050864369252f313d3b7cb3095e5a074ed95e8bb8159b03a7adbf00b9281daa40e5865a893925ef0840534a7e172b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000980830f4240808601499be94e9d80a0000000000000000000000000000000000000000000000000000000000000503ec0f8f1f8efa0ae9448de848b702908d937f87a458f2ce60ef83b99c9612b085182d2b3251289a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000780830f4240808601499be9458880a00000000000000000000000000000000000000000000000000000000000003e31
f8f3f8efa0f4aee41be5fd2fc9bda4983cc1f8ad9a007a924f42a241d5841cbce81da4584aa074ed95e8bb8159b03a7adbf00b9281daa40e5865a893925ef0840534a7e172b594407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000a80830f4240808601499be9546580a0000000000000000000000000000000000000000000000000000000000000968ec0c0
f901e5f8efa0a52ac2737ecead3a7aaf570c752850702828508592f956676f9bed4eac58b025a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000880830f4240808601499be94a6280a0000000000000000000000000000000000000000000000000000000000002c356c0f8f1f8efa0ae9448de848b702908d937f87a458f2ce60ef83b99c9612b085182d2b3251289a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000780830f4240808601499be9458980a00000000000000000000000000000000000000000000000000000000000003a1a
f8f3f8efa0b9cd1ba4dea2190b8cb486560b758009f2d067aa3379d86c8b32e4cbc3125e4da074ed95e8bb8159b03a7adbf00b9281daa40e5865a893925ef0840534a7e172b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000b80830f4240808601499be95d7780a000000000000000000000000000000000000000000000000000000000000180cfc0c0
f8f3f8efa0e457aab10cb22c52104da50d17ea5a8a97e49176bf77e1daaa583474e39be7aba074ed95e8bb8159b03a7adbf00b9281daa40e5865a893925ef0840534a7e172b594407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000c80830f4240808601499be9717e80a0000000000000000000000000000000000000000000000000000000000001331ec0c0
f8f3f8efa01c412e68e15d35ed0d4fc269058fce34bb6109ed8c5da4f5e46d63ba5c9e1ba9a074ed95e8bb8159b03a7adbf00b9281daa40e5865a893925ef0840534a7e172b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000d80830f4240808601499be981fe80a00000000000000000000000000000000000000000000000000000000000006cfac0c0
f8f3f8efa01ea661d8a9b3b6d5ca19347dd3d15adb2e794ba4a2a739b668a61644139e1feba074ed95e8bb8159b03a7adbf00b9281daa40e5865a893925ef0840534a7e172b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000e80830f4240808601499be9890980a00000000000000000000000000000000000000000000000000000000000001629c0c0
f8f3f8efa00841919fc04907545d31d9cdfdf3f5d005cf966026827b9314c707fef121026aa074ed95e8bb8159b03a7adbf00b9281daa40e5865a893925ef0840534a7e172b594407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000f80830f4240808601499be98c0d80a00000000000000000000000000000000000000000000000000000000000013da3c0c0
f8f3f8efa00841919fc04907545d31d9cdfdf3f5d005cf966026827b9314c707fef121026aa074ed95e8bb8159b03a7adbf00b9281daa40e5865a893925ef0840534a7e172b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000f80830f4240808601499be98c0780a0000000000000000000000000000000000000000000000000000000000001587bc0c0
f901e5f8efa034d8b5ee2ca883faf16e3caeb2a8235b922e4a502ee968ef3fc9065bf96c4664a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001080830f4240808601499be99e3980a00000000000000000000000000000000000000000000000000000000000004cbec0f8f1f8efa00841919fc04907545d31d9cdfdf3f5d005cf966026827b9314c707fef121026aa074ed95e8bb8159b03a7adbf00b9281daa40e5865a893925ef0840534a7e172b594407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000f80830f4240808601499be98c0d80a00000000000000000000000000000000000000000000000000000000000013da3
f8f3f8efa046a4f3c9cce7dffc620a2b5b61db7d65cd6ebeb265610f9c3b63a84b1c89d1dca0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001180830f4240808601499be9a3c680a00000000000000000000000000000000000000000000000000000000000009410c0c0
f8f3f8efa0a2d3f0276f151d9e1480243546a5a38bfe2ce72a4da091b80412a711b2d03921a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000980830f4240808601499be96d9c80a0000000000000000000000000000000000000000000000000000000000005133dc0c0
f8f3f8efa07e95e08472e83c1803afcc84d8bd943d0285ec8640263a3c1455bcd0fbfd7094a074ed95e8bb8159b03a7adbf00b9281daa40e5865a893925ef0840534a7e172b594407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001080830f4240808601499be99ced80a00000000000000000000000000000000000000000000000000000000000021b33c0c0
f8f3f8efa0acb571e2155a186fb55706f52b19d72ab0344e634fd6f9d0f771c8ba4a40ef29a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001280830f4240808601499be9acab80a0000000000000000000000000000000000000000000000000000000000000d07ac0c0
f8f3f8efa0313f1d1ccb05ec001dc39bc002099530876d1592c7b0e9ff48fd25a0c6bb385fa0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000a80830f4240808601499be9acd680a00000000000000000000000000000000000000000000000000000000000011884c0c0
f8f3f8efa0548f48b9d42c438ef5c90aea01401b26acc6f94d217756121409878e60aa60b2a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000b80830f4240808601499be9bc0c80a0000000000000000000000000000000000000000000000000000000000000ad2bc0c0
f901e5f8efa0545f5c31f5adec2b3ab663faa849d281bd21815cc95abf1f8d2d37605d75b264a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001180830f4240808601499be9b83d80a00000000000000000000000000000000000000000000000000000000000037146c0f8f1f8efa00841919fc04907545d31d9cdfdf3f5d005cf966026827b9314c707fef121026aa074ed95e8bb8159b03a7adbf00b9281daa40e5865a893925ef0840534a7e172b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000f80830f4240808601499be98c0780a0000000000000000000000000000000000000000000000000000000000001587b
f8f3f8efa027dc912f644898db30296acb70ba8952f86b2e9c123f08d576ae4f3dda42a1daa0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000c80830f4240808601499be9c64080a0000000000000000000000000000000000000000000000000000000000002aa74c0c0
f8f3f8efa09a3a43febbb9c9ba6598efc08c4c256d0f0fd640cd49bfa80499accd42bf70a0a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001280830f4240808601499be9e3f480a0000000000000000000000000000000000000000000000000000000000000658dc0c0
f8f3f8efa09b13386094d588494fa7b28b8b6758f93439c5c44f3592b25c3fe5c6d48063c0a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000d80830f4240808601499be9e87b80a00000000000000000000000000000000000000000000000000000000000003338c0c0
f8f3f8efa06d307e1c3ee8509a88ce3a12ecc01b59fe68f628b2f33d74e9e0039daf9415eba0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001380830f4240808601499be9b87480a00000000000000000000000000000000000000000000000000000000000042d00c0c0
f8f3f8efa0af321b01a29cce8109082baded6f9de05bf7b5e6d07f6cb0b860c5344be9c805a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000e80830f4240808601499be9ecd680a0000000000000000000000000000000000000000000000000000000000000093cc0c0
f8f3f8efa04a4a61e86bf6f960f205adea65d072b73f853d6e395b2df84ed16b11df19de2da0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001480830f4240808601499be9ed1780a00000000000000000000000000000000000000000000000000000000000005a81c0c0
f8f3f8efa0e8d35b4d57bfa7a22b82a473c4bb326401b6e375e6a1349af7154eb13d002324a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001580830f4240808601499be9f35280a0000000000000000000000000000000000000000000000000000000000000efddc0c0
f8f3f8efa04388a9dd534af696e90987c5d0d1c12fb7448e9f64c5a827eabe87cb70de766da0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001680830f4240808601499bea009580a000000000000000000000000000000000000000000000000000000000000011ebc0c0
f8f3f8efa0d0a8672b9bc15a76c9a9ae8a294bf476fed00838c8e539fba4e62966b36ab963a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001780830f4240808601499bea035880a000000000000000000000000000000000000000000000000000000000000052cfc0c0
f8f3f8efa0a96119b8e7db36958a4efc1a49704c19aca4e918c12f8dafa352642ee0ab1400a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001380830f4240808601499be9eaa880a00000000000000000000000000000000000000000000000000000000000036aadc0c0
f8f3f8efa0d7f146ae1a13a631ae9a85c99a42a309b44a05a0bd9fb49b41227e345de73433a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200000f80830f4240808601499be9ef3680a000000000000000000000000000000000000000000000000000000000000339e2c0c0
f8f3f8efa08d337e750b504087a343cac87b74c48cb84000924d472c5ce1641bea60e8db3ba0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001480830f4240808601499bea15d680a00000000000000000000000000000000000000000000000000000000000020b04c0c0
f8f3f8efa004504dd71b55eacce99311e252f819526014e633f28c8f8801d42e22ddbb3573a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001880830f4240808601499bea093280a00000000000000000000000000000000000000000000000000000000000033881c0c0
f8f3f8efa026d396e921287ce73745d3dedcb1e7ec6c03703840dbac50a069ab3fcb4b0a31a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001080830f4240808601499bea181d80a000000000000000000000000000000000000000000000000000000000000420a2c0c0
f8f3f8efa0e6a600fa105c021b08adee5eca16ee7d84817c04282fef99723fb9e6a34ab452a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001180830f4240808601499bea4bc580a000000000000000000000000000000000000000000000000000000000000020ecc0c0
f8f3f8efa02c46ec302e05f80f5cab870b529a0ecc1350ee7476af193bc9e4169d053c26d3a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001980830f4240808601499bea31eb80a000000000000000000000000000000000000000000000000000000000000363e4c0c0
f8f3f8efa00f4ed696f49312b82b7882be9c259c317381687b7c438e56b9a3d37ba226e448a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001280830f4240808601499bea4f4180a00000000000000000000000000000000000000000000000000000000000012917c0c0
f8f3f8efa04fab8024dd87b0ef7fe1e651bb815f3d8d0f2dc28c3f00803dde7417c74134c0a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001580830f4240808601499bea305e80a00000000000000000000000000000000000000000000000000000000000046636c0c0
f8f3f8efa0f0211669b8ca33d94abd3b35d72a3aba0894cc2f0059271c94f795d84063caa6a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001a80830f4240808601499bea5d2b80a0000000000000000000000000000000000000000000000000000000000001f2b3c0c0
f8f3f8efa0c0917c350347d1fd7f3fc816f3373e57d0213335a6f4ab64ec9686f520af6ed5a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001680830f4240808601499bea684580a00000000000000000000000000000000000000000000000000000000000015292c0c0
f8f3f8efa03980d1c7f3e0c6f8b84372aa0bab2fad96134571d164c8c61a674420fda962a7a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001780830f4240808601499bea7a4580a0000000000000000000000000000000000000000000000000000000000000b3b2c0c0
f8f3f8efa02676cd8101ba440aa0b7f4a9f10fc90ff0f6ab641895b30d233cb363818e337aa0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001b80830f4240808601499bea768f80a0000000000000000000000000000000000000000000000000000000000001efd6c0c0
f8f3f8efa075993bc4a752ffb1b264740394ea54c47bd1479b480a071653dd853428483a7aa0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001380830f4240808601499bea600080a00000000000000000000000000000000000000000000000000000000000049bb0c0c0
f8f3f8efa0cd3207112054717afec238f55ff2fb1b4757bd83f2c49f9645340bddf16256c9a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001880830f4240808601499bea84b480a0000000000000000000000000000000000000000000000000000000000001ccfac0c0
f8f3f8efa054bd2c83929709ac6fa25835cbe5482240e8ab3281cca533072aeff55ab39813a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001980830f4240808601499bea9c6b80a00000000000000000000000000000000000000000000000000000000000009e36c0c0
f8f3f8efa095d0c4859de4d5f26c92ba8459fa50b1527492975234f03a055c72ec664d75ada0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001480830f4240808601499bea999f80a0000000000000000000000000000000000000000000000000000000000001b8a6c0c0
f8f3f8efa01b41e9102521d7c0c315b1f065fcd0675ac5ddaa2ddd3f525d499853c00da58aa0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001a80830f4240808601499beaa5d680a0000000000000000000000000000000000000000000000000000000000000d4e7c0c0
f8f3f8efa0bade645073a42c3d1d0d624fd73717f65a73d3be798613ed9b61827e41111d2ea0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001580830f4240808601499beab04a80a0000000000000000000000000000000000000000000000000000000000000706bc0c0
f8f3f8efa0e6589e6635e4ad25ae7818aca2b780ff58f2d82bf64ec47d1d3614fcbe526a27a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001680830f4240808601499beab78880a0000000000000000000000000000000000000000000000000000000000000a064c0c0
f8f3f8efa02c178fa60aea1272de0011a96573986005018f651927f532d72f0a74beb079f9a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001b80830f4240808601499beab1c680a00000000000000000000000000000000000000000000000000000000000020fa8c0c0
f8f3f8efa073c8ac00303234de607407ba9398f3ab36897785c50e52230d45c75da82f445da0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001780830f4240808601499beac10f80a00000000000000000000000000000000000000000000000000000000000020f62c0c0
f8f3f8efa022a32fd6bf4a9eb7adaa3f77a3958109c44f49ba1e91617a04b4dba944a4b7d4a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001880830f4240808601499beadbe780a00000000000000000000000000000000000000000000000000000000000010305c0c0
f8f3f8efa00b10594db7ecb7621e5525b0b6ec5abfd2cbd33aa4f546c5070a7ff5f0821684a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001c80830f4240808601499bea8fde80a00000000000000000000000000000000000000000000000000000000000089f05c0c0
f8f3f8efa0691b8a7120256ee2b4b49023f48a0b1cfa8f3612853c2387356001ab63cded96a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001d80830f4240808601499beafa1880a0000000000000000000000000000000000000000000000000000000000000ab6ec0c0
f8f3f8efa0328af83bfd5efaa4769e37d0122549de2cb5707b019a99dc4a89e0fdc6716aada0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001980830f4240808601499beaea1a80a00000000000000000000000000000000000000000000000000000000000023be2c0c0
f8f3f8efa0c0510a51466c204caf187a776e3e86e61a13d58e4ca58de75360206a5316a9ada0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001c80830f4240808601499beacc9a80a000000000000000000000000000000000000000000000000000000000000634fec0c0
f8f3f8efa0a4863211fd85e271c82c43b04bf55b1ef17301d539f54695db4eca604de848fea0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001a80830f4240808601499beb070c80a0000000000000000000000000000000000000000000000000000000000002cc9bc0c0
f8f3f8efa0a8a14019955ff6ebb94f0ed86496d05ac802f4fe9db5f5804136695f49cdf84ca0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001b80830f4240808601499beb2ab080a00000000000000000000000000000000000000000000000000000000000004a5dc0c0
f8f3f8efa048f347b9d9b6ea416c729db61a1892c6b2c9a3194ba890f59a6de677cc27fb0fa0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001d80830f4240808601499beb196680a0000000000000000000000000000000000000000000000000000000000002f245c0c0
f8f3f8efa07c0a67e646434a32abc3de3f03a142c847ce6c51672e7bbd42cbdd66151b7ddfa0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001e80830f4240808601499beb042d80a0000000000000000000000000000000000000000000000000000000000004dab0c0c0
f8f3f8efa0f9068922b9064435ddff0f0d48db7f4bb67f35adfa6e11c7b50d2d21c4c3b393a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001e80830f4240808601499beb3ee280a0000000000000000000000000000000000000000000000000000000000001ae46c0c0
f8f3f8efa092d78e2a2cae49fb4ad34c733409e192c76c72b706a4bec4ce3442f843695ea2a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001c80830f4240808601499beb302880a0000000000000000000000000000000000000000000000000000000000003355ac0c0
f8f3f8efa024eb76f9df4cd1947965ab2eaa3900eea96fb8ec556b83d90f9cc85e83f38276a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001f80830f4240808601499beb551b80a0000000000000000000000000000000000000000000000000000000000000fb9ec0c0
f8f3f8efa0f03337d44374386e3fcdae26a42bc669eda32579346c967f801f6353cc7af8e7a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002080830f4240808601499beb62f680a0000000000000000000000000000000000000000000000000000000000002a9a3c0c0
f8f3f8efa03c75383ab74fb9f80c4a6f55a186cc08001ee9842f335a65902f7a2db9a1bc56a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002180830f4240808601499beb852980a000000000000000000000000000000000000000000000000000000000000152fec0c0
f8f3f8efa0ed6e5cad16c98f77353950408594a3c72594b71337c84dc12548e884570a7083a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001d80830f4240808601499beb58b480a0000000000000000000000000000000000000000000000000000000000005d64fc0c0
f8f3f8efa0767c5a6025b3fe3d91b7f5c344f3a9e690f605ecb392062cbb9c5faeed34a071a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001e80830f4240808601499beba14b80a00000000000000000000000000000000000000000000000000000000000007480c0c0
f8f3f8efa0f540dde2f457214a1c00fae6f75ba466016956592c37f0bf5e042d569f11d0e5a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001f80830f4240808601499beba8b080a00000000000000000000000000000000000000000000000000000000000000ac0c0c0
f8f3f8efa07ae78cbcc719621397c5a7e0891834862df53dcdd563c75724dab7752ffc0b45a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200001f80830f4240808601499beb40a280a0000000000000000000000000000000000000000000000000000000000008f5e2c0c0
f8f3f8efa02c2c199e3c917c001609def65a86ee32308e91c2395b0ac7c3ddef61308987b8a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002280830f4240808601499beb971d80a000000000000000000000000000000000000000000000000000000000000232ffc0c0
f8f3f8efa0db146baa751ed32aa84462ef53b65eddaee46850ce7077690f037a6ea9e46e6ba0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002380830f4240808601499bebb36580a0000000000000000000000000000000000000000000000000000000000001ce61c0c0
f8f3f8efa001f2aa57f616b296c5bd3b312cc1673a608ee0f847b152ec0448a8462360cc78a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002080830f4240808601499bebaeb980a000000000000000000000000000000000000000000000000000000000000286c0c0c0
f8f3f8efa08cf3ed95e951111b29c93fa69aaf367ca0706cb7501bfd0bc09f77f62896d575a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002080830f4240808601499bebab1f80a0000000000000000000000000000000000000000000000000000000000003c1f5c0c0
f8f3f8efa0804ffa27ee089c237fc6a26421bcfdd6def1b78c060ff9d851b8fe109be77316a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002180830f4240808601499bebcef880a0000000000000000000000000000000000000000000000000000000000001308dc0c0
f8f3f8efa068b5f29fa39440eb903739a33588d5412324b2ec415728dc3a24de66c2f7781ea0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002480830f4240808601499bebcb0580a0000000000000000000000000000000000000000000000000000000000001b13ec0c0
f8f3f8efa03863993d6869f1ea102a2e39d43bbd4cba9ab6c15c40f08882e54117f436e1cba0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002580830f4240808601499bebe17780a00000000000000000000000000000000000000000000000000000000000013ed3c0c0
f8f3f8efa00b81ffefd7c14325237726f4261d8a5234ade02569b1ed22d29eb754a35c7b97a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002180830f4240808601499bebda5380a0000000000000000000000000000000000000000000000000000000000001da18c0c0
f8f3f8efa05ed4bffe533d4bf104d020cad3dc20c9abe9dd66ca77d85d078150cb0355a9bfa0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002280830f4240808601499bebdf4a80a0000000000000000000000000000000000000000000000000000000000001cafcc0c0
f8f3f8efa0b1b8f51be1e9837b0d933259e373b5f452745aa7fcac5705633214ee922358e7a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002680830f4240808601499bebf26d80a0000000000000000000000000000000000000000000000000000000000000daa5c0c0
f8f3f8efa041151e2bbee318c196822d638be9b937438e0006d56436090f4ec7dd32293d7ca0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002780830f4240808601499bebfea680a0000000000000000000000000000000000000000000000000000000000001b85ec0c0
f8f3f8efa0532f7a3031cbee6378cdd41d4ac1cccac1fb4cb6a16c3efc60a41f4fd12c03cba0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002280830f4240808601499bebf2a780a00000000000000000000000000000000000000000000000000000000000033aafc0c0
f8f3f8efa0916c7bd36ca217f9ba80ef3b156ca95cefde1d96a8e76a609e60393e11eae364a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002380830f4240808601499bebf6de80a000000000000000000000000000000000000000000000000000000000000561ebc0c0
f8f3f8efa0a97e7c11bb73076a076c8c0e58e9b0bb7c2c31001ec774a0147d30480a4a6ea6a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002380830f4240808601499bec1b7d80a0000000000000000000000000000000000000000000000000000000000002fa24c0c0
f8f3f8efa0ae7186fb08ede840f9e216d0595d9909d9221db96eedd65a2292528aee07dbdaa0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002480830f4240808601499bec39d280a0000000000000000000000000000000000000000000000000000000000000cc8fc0c0
f8f3f8efa055bdf8020faaf99a67ecfee3134d146015b9bcac5921bb5e433ab0f2f9a07cdba0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002580830f4240808601499bec456480a000000000000000000000000000000000000000000000000000000000000032e5c0c0
f8f3f8efa0424161518705e296c430cc3705a3e4397ab61d29ee68fca5f2f3a65b5211a4eca0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002680830f4240808601499bec49ad80a000000000000000000000000000000000000000000000000000000000000035f8c0c0
f8f3f8efa07caad155a0c98d102068ab959076b69449d74632805e173976690e6c5c3aab4da0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002780830f4240808601499bec4e2180a00000000000000000000000000000000000000000000000000000000000001d39c0c0
f8f3f8efa08a033322e2fa721687e07ea654fd51ec3f5c5ee4656a1f97f8dc3c89096f9566a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002480830f4240808601499bec415a80a0000000000000000000000000000000000000000000000000000000000001695cc0c0
f8f3f8efa0f834b5b07c213c36b9f5051e514ad5e778e92dcb6e376484c7ceaa28726f1296a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002580830f4240808601499bec544980a00000000000000000000000000000000000000000000000000000000000001d79c0c0
f8f3f8efa06d4d43b1a2543c689ebb2d098cd953d7c774be1760bea0c8d2d2f8dbda164c14a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002880830f4240808601499bec516f80a0000000000000000000000000000000000000000000000000000000000000f268c0c0
f8f3f8efa0d0a8023e5335685e04686ad5b15852bdf7184ff651a0961ceb774e19a05e35afa0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002980830f4240808601499bec5eb680a00000000000000000000000000000000000000000000000000000000000009be4c0c0
f8f3f8efa023fadf819a3863e4a93c41434b5cab8dca00810bfacb68299f8484b8bef06569a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002680830f4240808601499bec579d80a000000000000000000000000000000000000000000000000000000000000137dcc0c0
f8f3f8efa07bc0eddb475c5bfabc009af858c9c4f71a149d47d812a681c725476f61addfdfa0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002a80830f4240808601499bec680380a0000000000000000000000000000000000000000000000000000000000000c18bc0c0
f8f3f8efa051520b9ab6c93891ccffe5ef86b863e26a5e0e5321564e09fb6ed28efd5f3d29a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002780830f4240808601499bec683880a0000000000000000000000000000000000000000000000000000000000000dba7c0c0
f8f3f8efa0a1eba7354ed89790e55807a98909ae4d1432c09c5fda4a596ff3c18fd688dd36a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002880830f4240808601499bec156280a000000000000000000000000000000000000000000000000000000000000920ebc0c0
f8f3f8efa01a9916fd59a2b50fb0f5632e5292e2e2ae7cc396802c9eaf958e2633f4c2a82fa0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002b80830f4240808601499bec730b80a0000000000000000000000000000000000000000000000000000000000001def1c0c0
f8f3f8efa080d5015387cf132799ab8fbbc47728a42ed3d575488a9fbe8a0419ccd3e62b78a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002880830f4240808601499bec747380a0000000000000000000000000000000000000000000000000000000000001ee61c0c0
f8f3f8efa0c4eedb3d830c255878443a401f2a604926a87e89dae5b29f4f29881f13760b00a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002980830f4240808601499bec853d80a000000000000000000000000000000000000000000000000000000000000097f4c0c0
f8f3f8efa061b0d9bf97c5ee334a50d6a06222085c75a06c550692812e06d86e20426ddaeba0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002c80830f4240808601499bec8b9080a00000000000000000000000000000000000000000000000000000000000002f86c0c0
f8f3f8efa020c829d6f3529b81fe5b0f91b488b9eb32cdf0f5c0ece6594e29844e8afc53a5a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002980830f4240808601499bec8da080a00000000000000000000000000000000000000000000000000000000000001706c0c0
f8f3f8efa0bcfac95ad81d1c161fbcbbec9bc4c9ab3f0f2b6178a60cf6a823dfd6ebeb32e5a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002d80830f4240808601499bec8fbb80a0000000000000000000000000000000000000000000000000000000000000f6c7c0c0
f8f3f8efa0f1607f93d23e2c2612bd920da27ab9cba770ca07bd2cf2a4feab2f72928f4b92a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002a80830f4240808601499bec8e5380a00000000000000000000000000000000000000000000000000000000000025c78c0c0
f8f3f8efa0b5f79b2c6d3859452fd03381c505b207f6973886e769ed503f57314145ae201ea0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002e80830f4240808601499bec9d4a80a00000000000000000000000000000000000000000000000000000000000020deac0c0
f8f3f8efa070277a11509194d7356edfa20e069b4b3c200004fda8a6afb349d2f7fb880ab8a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002f80830f4240808601499becb80680a00000000000000000000000000000000000000000000000000000000000014d2cc0c0
f8f3f8efa004d0a117563ef59133cf4822792572f36142f88376e02f6df9115bf5d3795bb1a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003080830f4240808601499becc9c080a00000000000000000000000000000000000000000000000000000000000000d2ec0c0
f8f3f8efa011ca4595454fe47edd693e409dc9acc3e2c509252eccb798f0b57ef953db1414a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002a80830f4240808601499bec90ae80a00000000000000000000000000000000000000000000000000000000000050078c0c0
f8f3f8efa0f072bf517f364c5e0520608596f87e65ffbab12cabe312e188506c0ff80d44d2a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002b80830f4240808601499beccf2880a0000000000000000000000000000000000000000000000000000000000001431ec0c0
f8f3f8efa035c8b6c28b93d7e0b92c4a35611f8072b8369776b739b99c9498c772f8f1e6f6a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002b80830f4240808601499becacef80a00000000000000000000000000000000000000000000000000000000000044f71c0c0
f8f3f8efa0b1e6074d836d71c5cdd4f65ccfdb4f6af010b905071d3496ac74942c3d3b909aa0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003180830f4240808601499beccc5780a0000000000000000000000000000000000000000000000000000000000001e09cc0c0
f8f3f8efa07c28dfafc08d1d261c8c622014d48bb4072260f4bb5a6ba277c2fa45b6bf3e2aa0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003280830f4240808601499bece4de80a0000000000000000000000000000000000000000000000000000000000001883cc0c0
f8f3f8efa0a9510a4e7a809e2818d7bf2629cb96a220575681994e9169c1f4ea396bf26202a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002c80830f4240808601499bece04580a0000000000000000000000000000000000000000000000000000000000001f284c0c0
f8f3f8efa0795522ad0583a8e396f0aba045a8f50fc274d6d06cb0a71fc21f2447d9738e91a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002c80830f4240808601499bece2ba80a0000000000000000000000000000000000000000000000000000000000002b536c0c0
f8f3f8efa06441d3b630bb8a062de40696a9c0ceacc2d94152c52841a87c073eca2bd38425a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002d80830f4240808601499becf9c880a0000000000000000000000000000000000000000000000000000000000001392fc0c0
f8f3f8efa055744c1090a7ccf2d2cb9209e3ae1b2a772520e6d54c10fd8155df76f167f652a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002e80830f4240808601499bed0a8380a000000000000000000000000000000000000000000000000000000000000003c3c0c0
f8f3f8efa04422e5903c71d04479ffcf25f5ba424317ace033be9de311a5e2a00c11da44e6a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002d80830f4240808601499bed057280a0000000000000000000000000000000000000000000000000000000000001493fc0c0
f8f3f8efa0a81f3b2b47a93793bec3fb0b310ba092ccff4e50fb2d04a7a4b77b2ccd1fd53aa0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002e80830f4240808601499bed16e280a0000000000000000000000000000000000000000000000000000000000001b077c0c0
f8f3f8efa061694dc7758c69f30739731337939c3d4bf4309c478d2682371011f6f91fe6d2a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003380830f4240808601499becf96980a0000000000000000000000000000000000000000000000000000000000005278bc0c0
f8f3f8efa09738b9a63ee59cea4f1ffc2de6c225e78c5f7ffb3dbc3f3ce1513066b019993da0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002f80830f4240808601499bed2d4880a0000000000000000000000000000000000000000000000000000000000001f074c0c0
f8f3f8efa080b3f511bb253b034cc6735dc48edf2bc0fd9840a8a26460b572614eb533ed9fa0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200002f80830f4240808601499bed0c9c80a0000000000000000000000000000000000000000000000000000000000004f4c4c0c0
f8f3f8efa0012617d9177440c99b49235a8bb621ca637cf2a372ca93ff348c88c38915e7a7a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003080830f4240808601499bed469c80a0000000000000000000000000000000000000000000000000000000000000d567c0c0
f8f3f8efa037bd61fd37261810aa1c59f4ec16690e0b8c7063791e17bb541e59282415b36da0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003080830f4240808601499bed4a5e80a00000000000000000000000000000000000000000000000000000000000018099c0c0
f8f3f8efa0b59c036aea9e59aa17e09eb83cf031b9272e849e6705d4cd563cc322e1cfe09aa0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003180830f4240808601499bed52ab80a0000000000000000000000000000000000000000000000000000000000001001bc0c0
f8f3f8efa06ab85f875c38896c1af5b4a6ef68e2d4cc6dbee5de58d23e6b3c861464da058ca0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003480830f4240808601499bed399980a00000000000000000000000000000000000000000000000000000000000036effc0c0
f8f3f8efa012117ab327bc88ecd205a6e8ae2e96bedc0692ef7cb80d3ccb8a9430ecaf43c4a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003280830f4240808601499bed60a880a00000000000000000000000000000000000000000000000000000000000009c2dc0c0
f8f3f8efa05c7b948fd788f5b091d7b1202a6f09258012bbfe0ccbbabfe081f0cd57e91b97a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003380830f4240808601499bed69f180a00000000000000000000000000000000000000000000000000000000000017ce3c0c0
f8f3f8efa0fc09664116fcb24b8cd48caaeb327061ef1740fd86d3ef3a922820c72ac11fd1a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003180830f4240808601499bed5e6880a00000000000000000000000000000000000000000000000000000000000030d17c0c0
f8f3f8efa0811f48e3a921c8885e1b2ff1fa2e430903ecc0ab57a127fd14d55601b18b4ec0a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003480830f4240808601499bed7dc880a0000000000000000000000000000000000000000000000000000000000000a090c0c0
f8f3f8efa0651da925ed9b627b4f9cbf50112569c0d929f1285b269ceccad4be1e6ffabaa4a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003280830f4240808601499bed851280a0000000000000000000000000000000000000000000000000000000000000109ac0c0
f8f3f8efa0fa9aa2000ce93d1d118623f8d0d1489e5ca54394b76a38fa6ff4c5de16268e17a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003380830f4240808601499bed87ce80a00000000000000000000000000000000000000000000000000000000000001754c0c0
f8f3f8efa0a258a7ed82a9e58e5a88760823ec30b1f65d642f8e617fe823e0391ac814b880a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003580830f4240808601499bed873b80a0000000000000000000000000000000000000000000000000000000000000ef4cc0c0
f8f3f8efa0430bd5a794ae2b992a4a4a84197e2195afd5df810599235c97a59524f00b09e8a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003680830f4240808601499bed947080a00000000000000000000000000000000000000000000000000000000000004bacc0c0
f8f3f8efa0b9e067495bd0ef882e09688fb74858eb5d93ec23a3751cc2ee1cfbe6e93c230ba0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003580830f4240808601499bed64dd80a0000000000000000000000000000000000000000000000000000000000004c1e9c0c0
f8f3f8efa0eb59a124406190b20ebbe41e08ec3a1e489b0d7dd69f20850736a0ab0680a93fa0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003680830f4240808601499beda00a80a00000000000000000000000000000000000000000000000000000000000003180c0c0
f8f3f8efa06188441a4f49412732009d4f85da86847f19caafd2e281251578ca70be13d9dfa0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003780830f4240808601499bed99fa80a000000000000000000000000000000000000000000000000000000000000113fac0c0
f8f3f8efa0d55b21fb2ecc56f76307146bce565c42c06aed77955fc060d0fd70a63313afdaa0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003880830f4240808601499beda8f580a0000000000000000000000000000000000000000000000000000000000000208fc0c0
f8f3f8efa09e72551bd9d3a1151547d1397c6dbe1f91a7665645de4c53adfda98cda5ef51aa0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003780830f4240808601499beda44980a0000000000000000000000000000000000000000000000000000000000000c178c0c0
f8f3f8efa0f499087ebf34a29fbcc647bd5f07660c3047c2deb9566bd31340f56abf18aa90a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003480830f4240808601499bed8ade80a000000000000000000000000000000000000000000000000000000000000351bcc0c0
f8f3f8efa0805ee8a2853d2531ea217ffbe9a0dc97bbba5fdef7f132dcb1f121a93b28c764a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003980830f4240808601499bedac6980a0000000000000000000000000000000000000000000000000000000000000bef0c0c0
f8f3f8efa069b12249b0f33b15c00859b3bff2f035be824ac778c7c062b1b8d41829a16d12a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003880830f4240808601499bedaf5c80a00000000000000000000000000000000000000000000000000000000000014835c0c0
f8f3f8efa0830ce46de6647d7febebd34ea072e893930b2895eab3f23d85778f593f7af19fa0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003580830f4240808601499bedb4e180a00000000000000000000000000000000000000000000000000000000000014743c0c0
f8f3f8efa0237e620d7071a0095b223fbea86bc62c7a54237e0bc8b50944e355f84bcd889fa0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003980830f4240808601499bedc0a480a00000000000000000000000000000000000000000000000000000000000004ec0c0c0
f8f3f8efa0f297d66dd0aac9c550938e27178ecdde20433ab7038c0bd17a61a7f8ab2af000a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003680830f4240808601499bedc62e80a0000000000000000000000000000000000000000000000000000000000000bb7dc0c0
f8f3f8efa01cc480617c8bedd2d4b85265f75acc43a9a07cc338d8247d933cb882b248bad5a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003a80830f4240808601499bedc64580a00000000000000000000000000000000000000000000000000000000000015ff0c0c0
f8f3f8efa0c4d7dd58dc26c6ae30dd0c29d23bbc2ded0de7e9a3f4f7a7a55873c8a1bfe3e8a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003780830f4240808601499bedd0e980a0000000000000000000000000000000000000000000000000000000000000aa4cc0c0
f8f3f8efa003aeedfc2fea4ec2ae29448f513a1ad157febb78cf33eae00f6013e9ad77d286a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003880830f4240808601499beddadc80a00000000000000000000000000000000000000000000000000000000000004ad6c0c0
f8f3f8efa0a1db256d3a3d29032d4b3e982e5dae0b7bae7027ef0460130ddea3d3410f8694a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003b80830f4240808601499bedd8b580a0000000000000000000000000000000000000000000000000000000000000c0cbc0c0
f8f3f8efa0d6b019c70bbd3c88d564ace5f6e7bef45c52eac897ad187c5c57b553674e25e2a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003980830f4240808601499bede05a80a00000000000000000000000000000000000000000000000000000000000002996c0c0
f8f3f8efa007e65cd8f8975ced72065264b9afd72e2be1e54ffb7e94616fc6d4a351e7832ea0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003c80830f4240808601499bede3b680a00000000000000000000000000000000000000000000000000000000000006db9c0c0
f8f3f8efa00ca7cbc392d1c651ef65599952ea4e5523bb3bdd98793b18a60320628787f825a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003d80830f4240808601499bedead280a0000000000000000000000000000000000000000000000000000000000002e20cc0c0
f8f3f8efa0d938404b8c338292703267ef2c63fa499dd0f379475731760c1c7e49c33080fba0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003a80830f4240808601499bede43b80a000000000000000000000000000000000000000000000000000000000000382c3c0c0
f8f3f8efa0f2bedc126aeaa73c0dfbb4d1c606ea66ff51f4169b399c4b24a70cc41d14b252a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003b80830f4240808601499bee109b80a0000000000000000000000000000000000000000000000000000000000000ff6ac0c0
f8f3f8efa099c316cdf21cbce79023525b73133ee1badc37052d1156a9ce138bd2946b4239a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003c80830f4240808601499bee1e9380a0000000000000000000000000000000000000000000000000000000000001f44fc0c0
f8f3f8efa0cc7b6c3bcedbfabf850398cf0b0c71cf2ae15bc19cfc18e11c0124ff3c99691aa0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003a80830f4240808601499bedb74a80a000000000000000000000000000000000000000000000000000000000000a9396c0c0
f8f3f8efa08560084806935f9d3bd64ba30fc8ef2f1502d7e88330aaecb1ec6e6406c7c638a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003b80830f4240808601499bee38bb80a000000000000000000000000000000000000000000000000000000000000121eec0c0
f8f3f8efa09c74db263eb2b97fe0f19c9713d90a62a25357cf2599048d87ec0cd04b18f897a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003c80830f4240808601499bee485480a00000000000000000000000000000000000000000000000000000000000048bdec0c0
f8f3f8efa095f25ee4d780575a9624a09ca1f5e6e34988e9257dc6c4f860e22c3761ce7b3ba0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003e80830f4240808601499bee0f9980a00000000000000000000000000000000000000000000000000000000000093cfec0c0
f8f3f8efa0da1e3f70d47f6683ca61d93590d40fa0818d6e79f2ea9080908fa4cdbaebab63a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003f80830f4240808601499bee811780a0000000000000000000000000000000000000000000000000000000000000237cc0c0
f8f3f8efa0f1b2681c4030aa7189a9fc5fe5e2c3b6874d514b4c078aaa3da2d6c512a3daf1a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004080830f4240808601499bee84ae80a000000000000000000000000000000000000000000000000000000000000113a9c0c0
f8f3f8efa035bb8b320d08e2d9df20c95eed56b06d36d4350ea25133d33902dc3ac61bf392a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003d80830f4240808601499bee382780a0000000000000000000000000000000000000000000000000000000000007a2a3c0c0
f8f3f8efa0521d78bc90416828bfd61eb79340d2672fb86aeb05e1ef6c71e047e09115a347a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004180830f4240808601499bee93ab80a0000000000000000000000000000000000000000000000000000000000000a72cc0c0
f8f3f8efa01fe90fa5c68b8252a6d89409f6c1c2566bb8e71c33e9b209fd6b6876b5d26fe9a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004280830f4240808601499bee9d9a80a000000000000000000000000000000000000000000000000000000000000015e3c0c0
f8f3f8efa09fbf2ef8bfb7439109bb55dd496798463fc9f3b964b6693c689766c189e49a61a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004380830f4240808601499beea08b80a000000000000000000000000000000000000000000000000000000000000025c1c0c0
f8f3f8efa0e7aa1311869eb992225b95bc1c40e8b0aa0c712afad0fafe9d3f033de9bc91c6a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003d80830f4240808601499bee811080a000000000000000000000000000000000000000000000000000000000000319b8c0c0
f8f3f8efa02e7b8ba9ac5842cc398bb3ffa3179a756309da3888a628814d68140e4e02c8c3a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004480830f4240808601499beea44180a0000000000000000000000000000000000000000000000000000000000001203ac0c0
f8f3f8efa00c0df08b2b8ddf8fba16e115ab10cd7067ec36efe583759c9e98e6b5f62133d4a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004580830f4240808601499beeb3be80a000000000000000000000000000000000000000000000000000000000000050fdc0c0
f8f3f8efa03670df0485426950c27fbb84ee4f9649f5bd76497e5c940763019093d7c1f3f5a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003e80830f4240808601499bee964080a000000000000000000000000000000000000000000000000000000000000413c9c0c0
f8f3f8efa0ca108c90efe794b1ebbcaf0bf6be77d6a7bc7060ba4d4f5775ad1920858f4589a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003f80830f4240808601499beec96a80a00000000000000000000000000000000000000000000000000000000000005772c0c0
f8f3f8efa0410551ad72d37069056013c641b456b98326c3fc068c256442051d0b64377125a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003e80830f4240808601499beea87b80a00000000000000000000000000000000000000000000000000000000000043adac0c0
f8f3f8efa0f474b6e779592d33da1096476a0bafc36f8225567448b06ebbb73afebae757e0a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200003f80830f4240808601499beedd7f80a00000000000000000000000000000000000000000000000000000000000024363c0c0
f8f3f8efa0a4e90789bf4385b23224a2429ca11a4755158b98184638a0719375a142ac7b02a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004080830f4240808601499beefac280a00000000000000000000000000000000000000000000000000000000000001ad3c0c0
f8f3f8efa038b2eacb14dc5fd665b943d57fef6a28c59ce685cee14120f8cf0eab933e7013a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004680830f4240808601499beeb97280a00000000000000000000000000000000000000000000000000000000000060410c0c0
f8f3f8efa07437a7886a9b349f9f93253b135df82e3daa77c8b1caec779ec0a6123b9a7a85a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004080830f4240808601499beecf8180a0000000000000000000000000000000000000000000000000000000000004d9b2c0c0
f8f3f8efa0c7b07c5cc4ba15e6196da9f39bfc4537aef78b94ab194e2c7ffd127084806158a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004180830f4240808601499beefdf580a0000000000000000000000000000000000000000000000000000000000001427ac0c0
f8f3f8efa0745e232333b39d260432d1403b12c8329d3170b2a36a30580bd153c9bf715d5ca0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004780830f4240808601499bef043f80a000000000000000000000000000000000000000000000000000000000000115cec0c0
f8f3f8efa0e6f861c9fe1a8c108a9a349b2950a4863e15c1f22c6173ff3cf3a959d0e87e98a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004280830f4240808601499bef0f2d80a00000000000000000000000000000000000000000000000000000000000016f5ec0c0
f8f3f8efa0feeb9638a9a8f3ccbb68a5af81f56d23f17b170a188ce3e14f9fa9af130caa1ea0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004880830f4240808601499bef134b80a0000000000000000000000000000000000000000000000000000000000002284fc0c0
f8f3f8efa0479ddd48d688aae0be664994183127821a0da9d544906085158895ddc384dddea0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004380830f4240808601499bef227380a000000000000000000000000000000000000000000000000000000000000190c3c0c0
f8f3f8efa061d96e7713765e91c69ad802a6e3b85090fcba718d13eeedacb1e09795029caca0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004980830f4240808601499bef2f3280a0000000000000000000000000000000000000000000000000000000000000e77bc0c0
f8f3f8efa0172ed2b8c0443753559675c3dea73e6d12bf3595c2cd1371aa8cecdc0247d8eaa0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004180830f4240808601499bef0c1680a0000000000000000000000000000000000000000000000000000000000004f07fc0c0
f8f3f8efa06e3952e1a78e07e32eea0fefbde418c671178d84c10f49ace5d4a084b7f1c643a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004280830f4240808601499bef499f80a0000000000000000000000000000000000000000000000000000000000003455bc0c0
f8f3f8efa04658cef57f898636088a4d66d5d65e3ded9150d7725f11947f87a7060645178da0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004480830f4240808601499bef373a80a0000000000000000000000000000000000000000000000000000000000004ce8ec0c0
f8f3f8efa088ee460806f1a40b6afbaa84fb1a885b19b6c9f60ac9b60c588e9175cdea89e8a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004a80830f4240808601499bef3c0b80a0000000000000000000000000000000000000000000000000000000000004acafc0c0
f8f3f8efa0a2872231c4fc9c0321c76f7b6a73600e84874215cfc8a2527259aa83534cee65a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004b80830f4240808601499bef768080a00000000000000000000000000000000000000000000000000000000000003aa8c0c0
f8f3f8efa0c2414dacde20271f21bfb99020835a9289d0510c14b2defdce1812b0d50672b3a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004c80830f4240808601499bef7b2b80a00000000000000000000000000000000000000000000000000000000000017297c0c0
f8f3f8efa0e5d195187a7d9469949032f9ad4410435e93ccf20c1b6a91acffbbd01c97e442a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004580830f4240808601499bef735680a0000000000000000000000000000000000000000000000000000000000002a141c0c0
f8f3f8efa08b7dc009330f5f99f265858516fac3c39a4883e793f75e13636bdd5d26967028a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004380830f4240808601499bef732980a000000000000000000000000000000000000000000000000000000000000308ddc0c0
f8f3f8efa096bef9076325938dab985c050d5df25b18c177bb320f4098ddb9a3b5390eee0ea0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004d80830f4240808601499bef8ea080a0000000000000000000000000000000000000000000000000000000000000c80fc0c0
f8f3f8efa009ca8a0f1afed8775299996d6a358191f9d0e3c3f491fbe0f528802d77abd676a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004680830f4240808601499bef950780a0000000000000000000000000000000000000000000000000000000000000ae2ac0c0
f8f3f8efa0e66672480ec3813526386cbd17647ff6cf43ef0b07987147d8acf60efa42029fa0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004780830f4240808601499bef9f3c80a00000000000000000000000000000000000000000000000000000000000002091c0c0
f8f3f8efa08f6c5e2836e15674d897e19252088573a955ed705fcf32102867ac3d6a4c2ebca0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004480830f4240808601499bef99b380a00000000000000000000000000000000000000000000000000000000000015a93c0c0
f8f3f8efa0482e1f8f4afe08096f8abd8ef620672e38d37726ce365eb657ba49cac8ef26f2a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004e80830f4240808601499bef9a0880a000000000000000000000000000000000000000000000000000000000000167f8c0c0
f8f3f8efa0fd6f1f552c8c1a148849b3a1b40b6557417bdb81320b206f6fb56f29c893a3e8a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004880830f4240808601499befa2bd80a0000000000000000000000000000000000000000000000000000000000001da91c0c0
f8f3f8efa09fd569dbdeeb3c0038de5762207e0930d0c90a706945dfa6eb5c8e9e2241252aa0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004f80830f4240808601499befacdf80a0000000000000000000000000000000000000000000000000000000000001055dc0c0
f8f3f8efa0bfc6500926248644223a1634c64516d229f6ac34bcd2a49a66f48ee8388758a6a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005080830f4240808601499befbb4280a0000000000000000000000000000000000000000000000000000000000000a03dc0c0
f8f3f8efa0ba54847751cbeab3b48d6c19d3aa877c93067486e3986da9d184947d7ea8c47ba0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004980830f4240808601499befbb0f80a000000000000000000000000000000000000000000000000000000000000133aec0c0
f8f3f8efa0c607469488234c11aab16f9549015ef3f06dff241322ca2d3038d1fcdf99df17a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004580830f4240808601499befac0080a00000000000000000000000000000000000000000000000000000000000030c7dc0c0
f8f3f8efa0487cb7a768549f98d3a649d7c9592277ca70cc006e6fafaa043aca8f924eb4b6a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004a80830f4240808601499befcb8380a0000000000000000000000000000000000000000000000000000000000000b047c0c0
f8f3f8efa0de75d7c165d8cce778d126efde16bebdbe6ea6606837201c4d12985c98c04059a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005180830f4240808601499befc4d380a0000000000000000000000000000000000000000000000000000000000001dd8dc0c0
f8f3f8efa0b59695851e14238cbe6867ab9c35cda3a0c291e1abc66157fd1339da1bfcdee4a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004b80830f4240808601499befd5c180a0000000000000000000000000000000000000000000000000000000000000b08fc0c0
f8f3f8efa0fe02a467a339c034e081662eb24d1443142eae2eab6610b9f3a7842f65b38335a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004680830f4240808601499befd2c380a000000000000000000000000000000000000000000000000000000000000100cfc0c0
f8f3f8efa0982f2e375872ffb275806a3db14e7b5d2d756ad4528c1cee699c7e4831b1ddf6a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005280830f4240808601499befdd2b80a00000000000000000000000000000000000000000000000000000000000004712c0c0
f8f3f8efa0aa4348f8d5c0823ebfc2d0f1003bd40f024f8ab2bcd369584f241e6ed7f72d27a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005380830f4240808601499befe27c80a00000000000000000000000000000000000000000000000000000000000005fa8c0c0
f8f3f8efa03d0570bcfc9e39dd14f444529f5eebc901461628899b6e074383b50ae760dbb0a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005480830f4240808601499befe8f180a00000000000000000000000000000000000000000000000000000000000001029c0c0
f8f3f8efa0bbb4727e64e6e771b9451d29036513665f55e8f32e13668e8c7454437fd2e010a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004780830f4240808601499befe0b580a0000000000000000000000000000000000000000000000000000000000000c0ecc0c0
f8f3f8efa023f817379c33dd41adc4a5851193b6a7bd8d746359e937768b28740b4c0daceba0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004880830f4240808601499befebba80a0000000000000000000000000000000000000000000000000000000000000bb6bc0c0
f8f3f8efa0ffbb4ea4e002a41ef6decb98b7654bc1578ce9b29f4105a6c52631961187112da0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004c80830f4240808601499befdff480a0000000000000000000000000000000000000000000000000000000000002459ac0c0
f8f3f8efa0f2adff36367452574dff60622db915ea79d024b2add13daacb573699a6509c52a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004980830f4240808601499beff67d80a0000000000000000000000000000000000000000000000000000000000002dfadc0c0
f8f3f8efa050025e0cf32a9a1f8473ba3ec1afffeb4c8a5e63fafcf64cf5b5ef658a940e11a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004a80830f4240808601499bf01b1c80a000000000000000000000000000000000000000000000000000000000000064e8c0c0
f8f3f8efa08f531281b23f2391d4f29ee3ede6e11f510c7836b232e9af1ec616c03460ae9ba0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005580830f4240808601499befeba880a00000000000000000000000000000000000000000000000000000000000049240c0c0
f8f3f8efa0763d7da06f43bd920bd046ff218212878a7ca029edcc00909bf264f9ceae50e5a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004d80830f4240808601499beffd3f80a00000000000000000000000000000000000000000000000000000000000056cd7c0c0
f8f3f8efa05600cf0293dbf0443f1b985241943382d13ca2f2e84e0e1182392c62845a4eefa0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004e80830f4240808601499bf040b480a00000000000000000000000000000000000000000000000000000000000001681c0c0
f8f3f8efa09149deb0057c9d8b4979b1fdbba50adec0c75a977b4998d53aaf206e78de5777a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005680830f4240808601499bf024c480a0000000000000000000000000000000000000000000000000000000000002a355c0c0
f8f3f8efa00dca13774b2d519b567798dd4098e231cac2e12d87fd02e463601830073bea53a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004b80830f4240808601499bf021ca80a00000000000000000000000000000000000000000000000000000000000033a29c0c0
f8f3f8efa033831d99532c818ed7a860f91137790f12d8648c43f712ce8f71448d2ca11ee8a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004f80830f4240808601499bf043b580a00000000000000000000000000000000000000000000000000000000000025a3ec0c0
f8f3f8efa02f45254807c5ba59f9b439dd616e911cf875609d561ae9d129d55b94b96b135aa0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005780830f4240808601499bf0468680a0000000000000000000000000000000000000000000000000000000000003f49ec0c0
f8f3f8efa09ac7e902fbd0299c5ab19e04a9d3bcf14c194a87be61e7c140bea0f7f604c0f6a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005880830f4240808601499bf0784280a0000000000000000000000000000000000000000000000000000000000000341ec0c0
f8f3f8efa05a466092be341b2cdd660d765d0fbb8324eb726a1b12c6cc579ca65ce274ebeaa0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005080830f4240808601499bf0620b80a0000000000000000000000000000000000000000000000000000000000003355ec0c0
f8f3f8efa0d9e7d199814c22173dbe5d6b5b431a0a974197a1e7923a16ba2fddd99b2cfe7fa0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005980830f4240808601499bf07cae80a00000000000000000000000000000000000000000000000000000000000013aecc0c0
f8f3f8efa0784e6098b4ae7cb3ec959eb6bb74e36d639c4181bcf4287724a055b02029fb78a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005a80830f4240808601499bf08d7c80a0000000000000000000000000000000000000000000000000000000000000726ec0c0
f8f3f8efa0466d335b48ab7ce62c2559712b8c46a69a3a04d429a389286484a69df3405e8ea0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005180830f4240808601499bf08ad080a0000000000000000000000000000000000000000000000000000000000001fb36c0c0
f8f3f8efa06af93f1713a3f10c0d61cbeb4564f6d1e16e209535dd10bdbb5af1c45729f0d7a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005b80830f4240808601499bf094de80a0000000000000000000000000000000000000000000000000000000000001abf0c0c0
f8f3f8efa08d59eeae7d2fd06d81795770619efdc357ed15e01b649ae1181ac7603a59cd2ca0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004c80830f4240808601499bf04ab780a0000000000000000000000000000000000000000000000000000000000007ce1ac0c0
f8f3f8efa004ead6ca31328d0e24d08697237b47bbf85e61214473d55cfb84e9e68b89a361a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004d80830f4240808601499bf0ab1280a000000000000000000000000000000000000000000000000000000000000115a4c0c0
f8f3f8efa00f5af75c450db186d4c606f10e4db8e85af93c022346a10bf4adbc64d96c9b97a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005c80830f4240808601499bf0ab0380a000000000000000000000000000000000000000000000000000000000000159e7c0c0
f8f3f8efa03f5f38b78ea4dffc3969e1a34402a328ad4ca4485bc0a1ee3f3b893b239c395ca0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005d80830f4240808601499bf0bd3980a0000000000000000000000000000000000000000000000000000000000000df17c0c0
f8f3f8efa01f8e1bd3d93acf2fec96582b235c39c368c0a2b399edb501bb6c6dbd31b5b77ba0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005e80830f4240808601499bf0c9b980a00000000000000000000000000000000000000000000000000000000000005033c0c0
f8f3f8efa030338eca06f9d467ab4899c88bbbb8c94d166530ce7d8422c12c63e0a4939cb5a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004e80830f4240808601499bf0ba1180a000000000000000000000000000000000000000000000000000000000000282cdc0c0
f8f3f8efa03f9c06fa0414e19133c956c294cc66ce45f6b59edda1a59fcc41d8199dce6f47a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005f80830f4240808601499bf0cf7c80a00000000000000000000000000000000000000000000000000000000000011b7fc0c0
f8f3f8efa0bd085991e1a5ee0691eacb54a1132f491d725be29d694f779761b6224e9a28a8a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005280830f4240808601499bf0a4be80a00000000000000000000000000000000000000000000000000000000000059ed8c0c0
f8f3f8efa0d4c284c8fe955ba92ce44e43e2be966356087d3dd6a0dd0ba525ffd35db0f0c9a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200004f80830f4240808601499bf0da5980a0000000000000000000000000000000000000000000000000000000000002334dc0c0
f8f3f8efa0913f5cba9f1a9edc5cf2e808aeecd0f3bf8025aa937bc9a56f584182ad992252a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005380830f4240808601499bf0ea9380a0000000000000000000000000000000000000000000000000000000000001c0c9c0c0
f8f3f8efa081f3de4cb58782e3172a72a413f0ca3bd609b64f4715bc7f43eef79453ac5e26a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200006080830f4240808601499bf0deb780a0000000000000000000000000000000000000000000000000000000000002fbfec0c0
f8f3f8efa066f033fa14f5d84e1f082dc9a5b469c9087f7331146ac2e39b9abb49d0714085a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005080830f4240808601499bf0f6f380a00000000000000000000000000000000000000000000000000000000000015969c0c0
f8f3f8efa0b9101450d7f307ae07c4a04a051346812a48df675ecb7ba5338fe1db8f0280b6a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005180830f4240808601499bf1093980a0000000000000000000000000000000000000000000000000000000000000439fc0c0
f8f3f8efa0678388d1976ff9c7f2f355067db02d9b08e9d3576c35035982212fc69f888732a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200006180830f4240808601499bf104b680a00000000000000000000000000000000000000000000000000000000000018809c0c0
f8f3f8efa092cc30e4b476c33d6cdd4d0dee16285610f142e92d8174ce0511dfce5631ddb0a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005480830f4240808601499bf101b380a0000000000000000000000000000000000000000000000000000000000002598ac0c0
f8f3f8efa0524c17616bccac99cc87d445b1b3a31e51c75b28845731adaf244e328212c9d7a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200006280830f4240808601499bf1194380a0000000000000000000000000000000000000000000000000000000000000bfb4c0c0
f8f3f8efa079dc2e3b4d4dd658765cde6cd33c6c362f27471588b1e42d68b56bd519ab1b32a0b30af3020ffa3efbcc1a583ac590baa6d114f776954456e13454eab35f5aa6b594f92c0f3e4825f09490ca264dc0cdacffeb566f06a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200006380830f4240808601499bf1242c80a00000000000000000000000000000000000000000000000000000000000001951c0c0
f8f3f8efa0f3cde3285a1f48cd05e674dadf99d58da66b1824ba300a82b7031851f4517715a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005580830f4240808601499bf1201480a00000000000000000000000000000000000000000000000000000000000014fd5c0c0
f8f3f8efa0f31b49b8a2a450a6145405a24f21075e44396e534c38feddbc9055b1e1e47163a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005680830f4240808601499bf131d580a0000000000000000000000000000000000000000000000000000000000000328bc0c0
f8f3f8efa0bcc9f97c38c9a4db928b2c622d89d098e3a777b9cfeb3e9ea196b08e736d17a6a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005780830f4240808601499bf1362a80a0000000000000000000000000000000000000000000000000000000000001ac7ac0c0
f8f3f8efa0acb5dbc9a0a0e41ed5b05e49a29af7aad28a6380f3ecc2c319d482f376debfa2a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005880830f4240808601499bf14c4780a00000000000000000000000000000000000000000000000000000000000010f1bc0c0
f8f3f8efa0ae7f00f41343e577f48c1fc2a03682610213d74e6cdc809531e37f6e0726702fa0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005280830f4240808601499bf10e5580a00000000000000000000000000000000000000000000000000000000000066097c0c0
f8f3f8efa04479ee926beb4f39152b06ba350572131d4dcaa54f4a26cc474345baeda09092a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005980830f4240808601499bf15b1a80a00000000000000000000000000000000000000000000000000000000000001e58c0c0
f8f3f8efa0391a99724f47651fc499feb1b9587dba63c57d95882614e222ee1d7fc3527c3ba0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005a80830f4240808601499bf15e7a80a00000000000000000000000000000000000000000000000000000000000007da3c0c0
f8f3f8efa032e03e397743a78a27bee4e076eec6d06008513930331a019d4a6723fb0594afa0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005380830f4240808601499bf15d5f80a0000000000000000000000000000000000000000000000000000000000000d352c0c0
f8f3f8efa0ec7c104bbd27ae66085fda9c57a94bc8b186fd3f905a913bc76ed5f230d5c278a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005b80830f4240808601499bf1665980a000000000000000000000000000000000000000000000000000000000000079d6c0c0
f8f3f8efa084de245ed1ee1cca7ce1cc77ae085e4c4f530533d3a958a31e6fade047e9b78fa0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005c80830f4240808601499bf16df880a00000000000000000000000000000000000000000000000000000000000008afcc0c0
f8f3f8efa0e745c25ccdeead4ee0592ee76594b90c6d9475646af579b401abdf75ee1ff0f4a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005480830f4240808601499bf1693f80a0000000000000000000000000000000000000000000000000000000000001621cc0c0
f8f3f8efa0130e3c542d66191260b3d2acba8aa6035015610b55a05746ce78f467e4ec807da0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005580830f4240808601499bf17bc980a0000000000000000000000000000000000000000000000000000000000000b4d2c0c0
f8f3f8efa062d6fa6a35dd3e319cda90132a8c5b0eab1632afe356fd60712ac6998d1a9b04a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005d80830f4240808601499bf1767180a00000000000000000000000000000000000000000000000000000000000025886c0c0
f8f3f8efa05dcaee9d4dd3d151609da0932190f5b5b925eee25e56adfeb8b1fe7806964150a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005680830f4240808601499bf1864080a00000000000000000000000000000000000000000000000000000000000014789c0c0
f8f3f8efa07a2aabe9a921f8b3bd6d924948a15a93a0f7c7db01bfcad9ca60b8a41150fc7ba0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005780830f4240808601499bf197a180a00000000000000000000000000000000000000000000000000000000000013139c0c0
f8f3f8efa0846b4d9c631d3bf54c84235faf69b5443cba97d991eb90d4e5302e440f2b1b84a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005880830f4240808601499bf1a7e580a0000000000000000000000000000000000000000000000000000000000001e536c0c0
f8f3f8efa0ac83d682ea467a7597cab3032c4c257d63f289ed95df83309e19698e74b7a694a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005980830f4240808601499bf1c0b280a00000000000000000000000000000000000000000000000000000000000023893c0c0
f8f3f8efa067bd350cddad24e478a229762c8b3889ef0c3856fc286ec7ab9555f556d10859a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005a80830f4240808601499bf1dd4f80a0000000000000000000000000000000000000000000000000000000000001e536c0c0
f8f3f8efa091b2f8986f02d39668a1db4fd0e1b4718d928ad55b75e6dbc2da700ee05c7104a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005b80830f4240808601499bf1f62b80a0000000000000000000000000000000000000000000000000000000000000bfc3c0c0
f8f3f8efa08c42420772fb4f397dd5d6fa2c28f40c2ee8176572480ce92cbffe7305da8377a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005c80830f4240808601499bf2012680a0000000000000000000000000000000000000000000000000000000000000432bc0c0
f8f3f8efa01a79835e698e0c7c5fe229f1f9f03a9e7af25270909dce87e77f8c656658fcf4a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005e80830f4240808601499bf194b480a0000000000000000000000000000000000000000000000000000000000009c016c0c0
f8f3f8efa01c1d1a073d0467757d10b993d311a6dc7ce7d41c3cfe9a4fced0964510756a65a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005f80830f4240808601499bf20c0980a0000000000000000000000000000000000000000000000000000000000001d197c0c0
f8f3f8efa0eaebb4e62293faf0419be514cf6be99febff1a68f99188dab974bbb8c2abd875a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005d80830f4240808601499bf2064980a0000000000000000000000000000000000000000000000000000000000002ebf9c0c0
f8f3f8efa002edc077444bb8f95dc223f5ae3046619c2dc7224ec86a3a4005536440357bd0a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200006080830f4240808601499bf223ee80a0000000000000000000000000000000000000000000000000000000000001b494c0c0
f8f3f8efa0093038619e720856eeecd37951d42a71a52bf71e6a5bf7a12ed4ec99fa83ab46a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200006180830f4240808601499bf23a6380a0000000000000000000000000000000000000000000000000000000000000b9bbc0c0
f8f3f8efa0ca38491cb196ce3292df83c038f4cafc4ca4281d720ee0301e5041e8c04f1cb9a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200006280830f4240808601499bf2450480a00000000000000000000000000000000000000000000000000000000000022c4cc0c0
f8f3f8efa0860b5e1b6320a5fa6d4d806053261a7fbe3b00521ae540ee044c16c59b3a43f5a0745bb6db3262859df599122d9a505e44c7d0d82587c3683478edfc77a8bc7d7f94407d73d8a49eeb85d32cf465507dd71d507100c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200006380830f4240808601499bf2614280a00000000000000000000000000000000000000000000000000000000000015b17c0c0
f8f3f8efa08fc3ca35a78aea9a3e457e83c7eedb197c061067ee200a6aa55283a71e495eeca0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005e80830f4240808601499bf22b6580a0000000000000000000000000000000000000000000000000000000000005db97c0c0
f8f3f8efa0111e672b998df74c2e8339562eb6a830ae24d935cf0513d75802ddbcb0ebb08fa0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200005f80830f4240808601499bf2740780a00000000000000000000000000000000000000000000000000000000000016892c0c0
f8f3f8efa05630d315d51ae6490c974bb76ec1892d33df5aacec9be31a72d78150b4936590a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200006080830f4240808601499bf286db80a0000000000000000000000000000000000000000000000000000000000000222bc0c0
f8f3f8efa05763307f1ad89730be5daa431b8a187a8c6267739ba3211d063340bad800eee4a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200006180830f4240808601499bf28a7080a000000000000000000000000000000000000000000000000000000000000225e5c0c0
f8f3f8efa0a1b6a9be62a5c305fa75b31f592ef0ffcf8435ff249a6d64f099b0ff5d2e2de9a0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200006280830f4240808601499bf2a63f80a0000000000000000000000000000000000000000000000000000000000000e81dc0c0
f8f3f8efa019e55e02c15ba8729543d3e84bd8960f4ea57ece14c508fcf715b97d73fc597da0cffc202279e137e898551b22024b42ec0970c3c8d9cfbc21cdbb67bfdd90a72f942bd26d8f796719923ff13d295644f9b45db1f730a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42180830200006380830f4240808601499bf2b31b80a000000000000000000000000000000000000000000000000000000000000187ffc0c0

View File

@ -1,11 +1,12 @@
# Root logger option
log4j.rootLogger=DEBUG, stdout
log4j.rootLogger=ERROR, stdout
# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
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=ERROR
# filter noisy classes
log4j.logger.block = ERROR
@ -19,7 +20,7 @@ log4j.logger.peermonitor = ERROR
log4j.logger.java.nio = ERROR
log4j.logger.io.netty = ERROR
log4j.logger.wire = ERROR
log4j.logger.VM = TRACE
log4j.logger.VM = ERROR
log4j.logger.main = ERROR
log4j.logger.trie = ERROR
log4j.logger.state = INFO
@ -28,6 +29,7 @@ log4j.logger.blockchain = TRACE
log4j.logger.txs = ERROR
log4j.logger.ui = ERROR
log4j.logger.gas = ERROR
log4j.logger.TCK-Test = INFO
log4j.logger.org.springframework = ERROR

View File

@ -142,4 +142,14 @@ root.hash.start = -1
GitHubTests.VMTest.loadLocal = false
# Key value data source values: [leveldb/redis]
keyvalue.datasource = leveldb
keyvalue.datasource = leveldb
# structured trace
# is the trace being
# collected in the
# form of objects and
# exposed to the user
# in json or any other
# convenient form.
vm.structured.trace = false
vm.structured.dir = vmtrace