diff --git a/framework/build.gradle b/framework/build.gradle index 877ed4e9073..8c4fbfc4583 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -216,13 +216,11 @@ createScript(project, 'org.tron.program.SolidityNode', 'SolidityNode') createScript(project, 'org.tron.program.FullNode', 'FullNode') createScript(project, 'org.tron.program.KeystoreFactory', 'KeystoreFactory') createScript(project, 'org.tron.program.DBConvert', 'DBConvert') -createScript(project, 'org.tron.tool.litefullnode.LiteFullNodeTool', 'LiteFullNodeTool') def releaseBinary = hasProperty('binaryRelease') ? getProperty('binaryRelease') : 'true' def skipSolidity = hasProperty('skipSolidity') ? true : false def skipKeystore = hasProperty('skipKeystore') ? true : false def skipConvert = hasProperty('skipConvert') ? true : false -def skipLite = hasProperty('skipLite') ? true : false def skipAll = hasProperty('skipAll') ? true : false if (releaseBinary == 'true') { artifacts { @@ -241,10 +239,6 @@ if (releaseBinary == 'true') { artifacts { archives(binaryRelease('buildDBConvertJar', 'DBConvert', 'org.tron.program.DBConvert'))} } - if (!skipLite) { - artifacts { - archives(binaryRelease('buildLiteFullNodeToolJar', 'LiteFullNodeTool', 'org.tron.tool.litefullnode.LiteFullNodeTool'))} - } } } diff --git a/framework/src/main/java/org/tron/tool/litefullnode/DbTool.java b/framework/src/main/java/org/tron/tool/litefullnode/DbTool.java deleted file mode 100644 index 5f43361eddf..00000000000 --- a/framework/src/main/java/org/tron/tool/litefullnode/DbTool.java +++ /dev/null @@ -1,199 +0,0 @@ -package org.tron.tool.litefullnode; - -import static org.fusesource.leveldbjni.JniDBFactory.factory; - -import com.google.common.collect.Maps; -import java.io.File; -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Iterator; -import java.util.Map; -import lombok.extern.slf4j.Slf4j; -import org.iq80.leveldb.CompressionType; -import org.iq80.leveldb.DB; -import org.iq80.leveldb.DBIterator; -import org.iq80.leveldb.Options; -import org.iq80.leveldb.WriteOptions; -import org.rocksdb.BlockBasedTableConfig; -import org.rocksdb.BloomFilter; -import org.rocksdb.RocksDBException; -import org.tron.common.utils.PropUtil; -import org.tron.tool.litefullnode.db.DBInterface; -import org.tron.tool.litefullnode.db.LevelDBImpl; -import org.tron.tool.litefullnode.db.RocksDBImpl; - -@Slf4j(topic = "tool") -public class DbTool { - - private static final String KEY_ENGINE = "ENGINE"; - public static final String ENGINE_FILE = "engine.properties"; - private static final String FILE_SEPARATOR = File.separator; - private static final String ROCKSDB = "ROCKSDB"; - - private static Map dbMap = Maps.newHashMap(); - - enum DbType { - LevelDB, - RocksDB - } - - /** - * Get the DB object according to the specified path, - * create db object when not exists, otherwise get it from the dbMap. - * - * @param sourceDir the parent path of db - * @param dbName db dir name - * - * @return db object - * - * @throws IOException IOException - * @throws RocksDBException RocksDBException - */ - public static DBInterface getDB(String sourceDir, String dbName) - throws IOException, RocksDBException { - Path path = Paths.get(sourceDir, dbName); - if (dbMap.containsKey(path.toString())) { - return dbMap.get(path.toString()); - } - DbType type = getDbType(sourceDir, dbName); - DBInterface db; - switch (type) { - case LevelDB: - db = openLevelDb(path); - dbMap.put(path.toString(), db); - break; - case RocksDB: - db = openRocksDb(path); - dbMap.put(path.toString(), db); - break; - default: - throw new IllegalStateException("Unexpected value: " + type); - } - return db; - } - - /** - * Close db. - * @param sourceDir db parentPath - * @param dbName db dirname - * @throws IOException IOException - */ - public static void closeDB(String sourceDir, String dbName) - throws IOException { - Path path = Paths.get(sourceDir, dbName); - DBInterface db = dbMap.get(path.toString()); - if (db != null) { - try { - dbMap.remove(path.toString()); - db.close(); - } catch (IOException e) { - logger.error("close db {} error: {}", path, e); - throw e; - } - } - } - - /** - * Close all dbs. - */ - public static void close() { - Iterator> iterator = dbMap.entrySet().iterator(); - while (iterator.hasNext()) { - Map.Entry next = iterator.next(); - try { - next.getValue().close(); - } catch (IOException e) { - logger.error("close db failed, db: {}", next.getKey(), e); - } - iterator.remove(); - } - } - - private static DbType getDbType(String sourceDir, String dbName) { - String engineFile = String.format("%s%s%s%s%s", sourceDir, FILE_SEPARATOR, - dbName, FILE_SEPARATOR, ENGINE_FILE); - if (!new File(engineFile).exists()) { - return DbType.LevelDB; - } - String engine = PropUtil.readProperty(engineFile, KEY_ENGINE); - if (engine.equalsIgnoreCase(ROCKSDB)) { - return DbType.RocksDB; - } else { - return DbType.LevelDB; - } - } - - private static LevelDBImpl openLevelDb(Path db) throws IOException { - DB database; - Options options = getLevelDbOptions(); - try { - database = factory.open(db.toFile(), options); - } catch (IOException e) { - if (e.getMessage().contains("Corruption:")) { - factory.repair(db.toFile(), options); - database = factory.open(db.toFile(), options); - } else { - throw e; - } - } - return new LevelDBImpl(database); - } - - private static RocksDBImpl openRocksDb(Path db) throws RocksDBException { - org.rocksdb.RocksDB database; - try (org.rocksdb.Options options = newDefaultRocksDbOptions()) { - database = org.rocksdb.RocksDB.open(options, db.toString()); - } catch (Exception e) { - throw e; - } - return new RocksDBImpl(database); - } - - private static org.rocksdb.Options newDefaultRocksDbOptions() { - org.rocksdb.Options options = new org.rocksdb.Options(); - - options.setCreateIfMissing(true); - options.setIncreaseParallelism(1); - options.setNumLevels(7); - options.setMaxOpenFiles(-1); - options.setTargetFileSizeBase(64 * 1024 * 1024); - options.setTargetFileSizeMultiplier(1); - options.setMaxBytesForLevelBase(512 * 1024 * 1024); - options.setMaxBackgroundCompactions(Math.max(1, Runtime.getRuntime().availableProcessors())); - options.setLevel0FileNumCompactionTrigger(4); - options.setLevelCompactionDynamicLevelBytes(true); - - BlockBasedTableConfig tableCfg = new BlockBasedTableConfig(); - tableCfg.setBlockSize(64 * 1024); - tableCfg.setBlockCacheSize(32 * 1024 * 1024); - tableCfg.setCacheIndexAndFilterBlocks(true); - tableCfg.setPinL0FilterAndIndexBlocksInCache(true); - tableCfg.setFilter(new BloomFilter(10, false)); - - options.setTableFormatConfig(tableCfg); - return options; - } - - private static Options getLevelDbOptions() { - CompressionType defaultCompressionType = CompressionType.SNAPPY; - int defaultBlockSize = 4 * 1024; - int defaultWriteBufferSize = 10 * 1024 * 1024; - long defaultCacheSize = 10 * 1024 * 1024L; - int defaultMaxOpenFiles = 100; - - Options dbOptions = new Options(); - - dbOptions.createIfMissing(true); - dbOptions.paranoidChecks(true); - dbOptions.verifyChecksums(true); - - dbOptions.compressionType(defaultCompressionType); - dbOptions.blockSize(defaultBlockSize); - dbOptions.writeBufferSize(defaultWriteBufferSize); - dbOptions.cacheSize(defaultCacheSize); - dbOptions.maxOpenFiles(defaultMaxOpenFiles); - - return dbOptions; - } -} diff --git a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java b/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java deleted file mode 100644 index 40c371c58e0..00000000000 --- a/framework/src/main/java/org/tron/tool/litefullnode/LiteFullNodeTool.java +++ /dev/null @@ -1,637 +0,0 @@ -package org.tron.tool.litefullnode; - -import com.beust.jcommander.JCommander; -import com.beust.jcommander.Parameter; -import com.beust.jcommander.ParameterException; -import com.beust.jcommander.internal.Lists; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Strings; -import com.google.common.collect.Maps; -import com.google.common.primitives.Bytes; -import com.google.common.primitives.Ints; -import com.google.common.primitives.Longs; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Objects; -import java.util.Optional; -import java.util.stream.Collectors; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.rocksdb.RocksDBException; -import org.tron.common.parameter.CommonParameter; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.FileUtil; -import org.tron.common.utils.PropUtil; -import org.tron.core.Constant; -import org.tron.core.capsule.BlockCapsule; -import org.tron.core.capsule.TransactionCapsule; -import org.tron.core.db2.common.Value; -import org.tron.core.db2.core.SnapshotManager; -import org.tron.core.exception.BadItemException; -import org.tron.tool.litefullnode.db.DBInterface; -import org.tron.tool.litefullnode.iterator.DBIterator; - -@Slf4j(topic = "tool") -@Deprecated -public class LiteFullNodeTool { - - private static final long START_TIME = System.currentTimeMillis() / 1000; - - private static long RECENT_BLKS = 65536; - - private static final String SNAPSHOT_DIR_NAME = "snapshot"; - private static final String HISTORY_DIR_NAME = "history"; - private static final String INFO_FILE_NAME = "info.properties"; - private static final String BACKUP_DIR_PREFIX = ".bak_"; - private static final String CHECKPOINT_DB = "tmp"; - private static final String CHECKPOINT_DB_V2 = "checkpoint"; - private static final String BLOCK_DB_NAME = "block"; - private static final String BLOCK_INDEX_DB_NAME = "block-index"; - private static final String TRANS_DB_NAME = "trans"; - private static final String TRANSACTION_RET_DB_NAME = "transactionRetStore"; - private static final String TRANSACTION_HISTORY_DB_NAME = "transactionHistoryStore"; - private static final String PROPERTIES_DB_NAME = "properties"; - - private static final String DIR_FORMAT_STRING = "%s%s%s"; - - private static List archiveDbs = Arrays.asList( - BLOCK_DB_NAME, - BLOCK_INDEX_DB_NAME, - TRANS_DB_NAME, - TRANSACTION_RET_DB_NAME, - TRANSACTION_HISTORY_DB_NAME); - - /** - * Create the snapshot dataset. - * - * @param sourceDir the original fullnode database dir, - * same with {storage.db.directory} in conf file. - * @param snapshotDir the path that stores the snapshot dataset - */ - public void generateSnapshot(String sourceDir, String snapshotDir) { - logger.info("Start create snapshot."); - long start = System.currentTimeMillis(); - snapshotDir = Paths.get(snapshotDir, SNAPSHOT_DIR_NAME).toString(); - try { - hasEnoughBlock(sourceDir); - List snapshotDbs = getSnapshotDbs(sourceDir); - split(sourceDir, snapshotDir, snapshotDbs); - mergeCheckpoint2Snapshot(sourceDir, snapshotDir); - // write genesisBlock , latest recent blocks and trans - fillSnapshotBlockAndTransDb(sourceDir, snapshotDir); - generateInfoProperties(Paths.get(snapshotDir, INFO_FILE_NAME).toString(), sourceDir); - } catch (IOException | RocksDBException e) { - logger.error("Create snapshot failed, {}.", e.getMessage()); - return; - } - long end = System.currentTimeMillis(); - logger.info("Create snapshot finished, take {} s.\n", (end - start) / 1000); - } - - /** - * Create the history dataset. - * - * @param sourceDir the original fullnode database dir, - * same with {storage.db.directory} in conf file. - * @param historyDir the path that stores the history dataset - */ - public void generateHistory(String sourceDir, String historyDir) { - logger.info("Start create history."); - long start = System.currentTimeMillis(); - historyDir = Paths.get(historyDir, HISTORY_DIR_NAME).toString(); - try { - if (isLite(sourceDir)) { - throw new IllegalStateException( - String.format("Unavailable sourceDir: %s is not fullNode data.", sourceDir)); - } - hasEnoughBlock(sourceDir); - split(sourceDir, historyDir, archiveDbs); - mergeCheckpoint2History(sourceDir, historyDir); - generateInfoProperties(Paths.get(historyDir, INFO_FILE_NAME).toString(), sourceDir); - } catch (IOException | RocksDBException e) { - logger.error("Create history failed, {}.", e.getMessage()); - return; - } - long end = System.currentTimeMillis(); - logger.info("Create history finished, take {} s.\n", (end - start) / 1000); - } - - /** - * Merge the history dataset into database. - * - * @param historyDir the path that stores the history dataset - * - * @param databaseDir lite fullnode database path - */ - public void completeHistoryData(String historyDir, String databaseDir) { - logger.info("Start merge history to lite node."); - long start = System.currentTimeMillis(); - BlockNumInfo blockNumInfo = null; - try { - // check historyDir is from lite data - if (isLite(historyDir)) { - throw new IllegalStateException( - String.format("Unavailable history: %s is not generated by fullNode data.", - historyDir)); - } - // 1. check block number and genesis block are compatible, - // and return the block numbers of snapshot and history - blockNumInfo = checkAndGetBlockNumInfo(historyDir, databaseDir); - // 2. move archive dbs to bak - backupArchiveDbs(databaseDir); - // 3. copy history data to databaseDir - copyHistory2Database(historyDir, databaseDir); - // 4. delete the duplicate block data in history data - trimHistory(databaseDir, blockNumInfo); - // 5. merge bak to database - mergeBak2Database(databaseDir); - // 6. delete snapshot flag - deleteSnapshotFlag(databaseDir); - } catch (IOException | RocksDBException | BadItemException e) { - logger.error("Merge history data to database failed, {}.", e.getMessage()); - return; - } - long end = System.currentTimeMillis(); - logger.info("Merge history finished, take {} s. \n", (end - start) / 1000); - } - - private List getSnapshotDbs(String sourceDir) { - List snapshotDbs = Lists.newArrayList(); - File basePath = new File(sourceDir); - Arrays.stream(Objects.requireNonNull(basePath.listFiles())) - .filter(File::isDirectory) - .filter(dir -> !archiveDbs.contains(dir.getName())) - .forEach(dir -> snapshotDbs.add(dir.getName())); - return snapshotDbs; - } - - private void mergeCheckpoint2Snapshot(String sourceDir, String historyDir) { - List snapshotDbs = getSnapshotDbs(sourceDir); - mergeCheckpoint(sourceDir, historyDir, snapshotDbs); - } - - private void mergeCheckpoint2History(String sourceDir, String destDir) { - mergeCheckpoint(sourceDir, destDir, archiveDbs); - } - - private void split(String sourceDir, String destDir, List dbs) throws IOException { - logger.info("Begin to split the dbs."); - if (!new File(sourceDir).isDirectory()) { - throw new RuntimeException(String.format("sourceDir: %s must be a directory ", sourceDir)); - } - File destPath = new File(destDir); - if (new File(destDir).exists()) { - throw new RuntimeException(String.format( - "destDir: %s is already exist, please remove it first", destDir)); - } - if (!destPath.mkdirs()) { - throw new RuntimeException(String.format("destDir: %s create failed, please check", destDir)); - } - Util.copyDatabases(Paths.get(sourceDir), Paths.get(destDir), dbs); - } - - private void mergeCheckpoint(String sourceDir, String destDir, List destDbs) { - logger.info("Begin to merge checkpoint to dataset."); - try { - List cpList = getCheckpointV2List(sourceDir); - if (cpList.size() > 0) { - for (String cp: cpList) { - DBInterface checkpointDb = DbTool.getDB(sourceDir + "/" + CHECKPOINT_DB_V2, cp); - recover(checkpointDb, destDir, destDbs); - } - } else { - DBInterface tmpDb = DbTool.getDB(sourceDir, CHECKPOINT_DB); - recover(tmpDb, destDir, destDbs); - } - } catch (IOException | RocksDBException e) { - throw new RuntimeException(e); - } - } - - private void recover(DBInterface db, String destDir, List destDbs) - throws IOException, RocksDBException { - try (DBIterator iterator = db.iterator()) { - for (iterator.seekToFirst(); iterator.hasNext(); iterator.next()) { - byte[] key = iterator.getKey(); - byte[] value = iterator.getValue(); - String dbName = SnapshotManager.simpleDecode(key); - byte[] realKey = Arrays.copyOfRange(key, dbName.getBytes().length + 4, key.length); - byte[] realValue = - value.length == 1 ? null : Arrays.copyOfRange(value, 1, value.length); - if (destDbs != null && destDbs.contains(dbName)) { - DBInterface destDb = DbTool.getDB(destDir, dbName); - if (realValue != null) { - destDb.put(realKey, realValue); - } else { - byte op = value[0]; - if (Value.Operator.DELETE.getValue() == op) { - destDb.delete(realKey); - } else { - destDb.put(realKey, new byte[0]); - } - } - } - } - } - } - - private void generateInfoProperties(String propertyfile, String databaseDir) - throws IOException, RocksDBException { - logger.info("Create {} for dataset.", INFO_FILE_NAME); - if (!FileUtil.createFileIfNotExists(propertyfile)) { - throw new RuntimeException("Create properties file failed."); - } - if (!PropUtil.writeProperty(propertyfile, Constant.SPLIT_BLOCK_NUM, - Long.toString(getLatestBlockHeaderNum(databaseDir)))) { - throw new RuntimeException("Write properties file failed."); - } - } - - private long getLatestBlockHeaderNum(String databaseDir) throws IOException, RocksDBException { - // query latest_block_header_number from checkpoint first - final String latestBlockHeaderNumber = "latest_block_header_number"; - List cpList = getCheckpointV2List(databaseDir); - DBInterface checkpointDb = null; - if (cpList.size() > 0) { - String lastestCp = cpList.get(cpList.size() - 1); - checkpointDb = DbTool.getDB(databaseDir + "/" + CHECKPOINT_DB_V2, lastestCp); - } else { - checkpointDb = DbTool.getDB(databaseDir, CHECKPOINT_DB); - } - Long blockNumber = getLatestBlockHeaderNumFromCP(checkpointDb, - latestBlockHeaderNumber.getBytes()); - if (blockNumber != null) { - return blockNumber; - } - // query from propertiesDb if checkpoint not contains latest_block_header_number - DBInterface propertiesDb = DbTool.getDB(databaseDir, PROPERTIES_DB_NAME); - return Optional.ofNullable(propertiesDb.get(ByteArray.fromString(latestBlockHeaderNumber))) - .map(ByteArray::toLong) - .orElseThrow( - () -> new IllegalArgumentException("not found latest block header number")); - } - - private Long getLatestBlockHeaderNumFromCP(DBInterface db, byte[] key) { - byte[] value = db.get(Bytes.concat(simpleEncode(PROPERTIES_DB_NAME), key)); - if (value != null && value.length > 1) { - return ByteArray.toLong(Arrays.copyOfRange(value, 1, value.length)); - } - return null; - } - - /** - * recent blocks, trans and genesis block. - */ - private void fillSnapshotBlockAndTransDb(String sourceDir, String snapshotDir) - throws IOException, RocksDBException { - logger.info("Begin to fill {} block, genesis block and trans to snapshot.", RECENT_BLKS); - DBInterface sourceBlockIndexDb = DbTool.getDB(sourceDir, BLOCK_INDEX_DB_NAME); - DBInterface sourceBlockDb = DbTool.getDB(sourceDir, BLOCK_DB_NAME); - DBInterface destBlockDb = DbTool.getDB(snapshotDir, BLOCK_DB_NAME); - DBInterface destBlockIndexDb = DbTool.getDB(snapshotDir, BLOCK_INDEX_DB_NAME); - DBInterface destTransDb = DbTool.getDB(snapshotDir, TRANS_DB_NAME); - // put genesis block and block-index into snapshot - long genesisBlockNum = 0L; - byte[] genesisBlockID = sourceBlockIndexDb.get(ByteArray.fromLong(genesisBlockNum)); - destBlockIndexDb.put(ByteArray.fromLong(genesisBlockNum), genesisBlockID); - destBlockDb.put(genesisBlockID, sourceBlockDb.get(genesisBlockID)); - - long latestBlockNum = getLatestBlockHeaderNum(sourceDir); - long startIndex = latestBlockNum - RECENT_BLKS + 1; - // put the recent blocks and trans in snapshot - for (long blockNum = startIndex; blockNum <= latestBlockNum; blockNum++) { - try { - byte[] blockId = getDataFromSourceDB(sourceDir, BLOCK_INDEX_DB_NAME, - Longs.toByteArray(blockNum)); - byte[] block = getDataFromSourceDB(sourceDir, BLOCK_DB_NAME, blockId); - // put block - destBlockDb.put(blockId, block); - // put block index - destBlockIndexDb.put(ByteArray.fromLong(blockNum), blockId); - // put trans - long finalBlockNum = blockNum; - new BlockCapsule(block).getTransactions().stream().map( - tc -> tc.getTransactionId().getBytes()) - .map(bytes -> Maps.immutableEntry(bytes, Longs.toByteArray(finalBlockNum))) - .forEach(e -> destTransDb.put(e.getKey(), e.getValue())); - } catch (IOException | RocksDBException | BadItemException e) { - throw new RuntimeException(e.getMessage()); - } - } - // copy engine.properties for block、block-index、trans from source if exist - copyEngineIfExist(sourceDir, snapshotDir, BLOCK_DB_NAME, BLOCK_INDEX_DB_NAME, TRANS_DB_NAME); - } - - private void copyEngineIfExist(String source, String dest, String... dbNames) { - for (String dbName : dbNames) { - Path ori = Paths.get(source, dbName, DbTool.ENGINE_FILE); - if (ori.toFile().exists()) { - Util.copy(ori, Paths.get(dest, dbName, DbTool.ENGINE_FILE)); - } - } - } - - private byte[] getGenesisBlockHash(String parentDir) throws IOException, RocksDBException { - long genesisBlockNum = 0L; - DBInterface blockIndexDb = DbTool.getDB(parentDir, BLOCK_INDEX_DB_NAME); - byte[] result = blockIndexDb.get(ByteArray.fromLong(genesisBlockNum)); - // when merge history, block-index db will be moved to bak dir and replaced by history - // so should close this db and reopen it. - DbTool.closeDB(parentDir, BLOCK_INDEX_DB_NAME); - return result; - } - - private static byte[] simpleEncode(String s) { - byte[] bytes = s.getBytes(); - byte[] length = Ints.toByteArray(bytes.length); - byte[] r = new byte[4 + bytes.length]; - System.arraycopy(length, 0, r, 0, 4); - System.arraycopy(bytes, 0, r, 4, bytes.length); - return r; - } - - private BlockNumInfo checkAndGetBlockNumInfo(String historyDir, String databaseDir) - throws IOException, RocksDBException { - logger.info("Check the compatibility of this history."); - String snapshotInfo = String.format( - DIR_FORMAT_STRING, databaseDir, File.separator, INFO_FILE_NAME); - String historyInfo = String.format( - DIR_FORMAT_STRING, historyDir, File.separator, INFO_FILE_NAME); - if (!FileUtil.isExists(snapshotInfo)) { - throw new FileNotFoundException( - "Snapshot property file is not found. maybe this is a complete fullnode?"); - } - if (!FileUtil.isExists(historyInfo)) { - throw new FileNotFoundException("history property file is not found."); - } - long snapshotBlkNum = Long.parseLong(PropUtil.readProperty(snapshotInfo, Constant - .SPLIT_BLOCK_NUM)); - long historyBlkNum = Long.parseLong(PropUtil.readProperty(historyInfo, Constant - .SPLIT_BLOCK_NUM)); - if (historyBlkNum < snapshotBlkNum) { - throw new RuntimeException( - String.format( - "History latest block number is lower than snapshot, history: %d, snapshot: %d", - historyBlkNum, snapshotBlkNum)); - } - // check genesis block is equal - if (!Arrays.equals(getGenesisBlockHash(databaseDir), getGenesisBlockHash(historyDir))) { - throw new RuntimeException(String.format( - "Genesis block hash is not equal, history: %s, database: %s", - Arrays.toString(getGenesisBlockHash(historyDir)), - Arrays.toString(getGenesisBlockHash(databaseDir)))); - } - return new BlockNumInfo(snapshotBlkNum, historyBlkNum); - } - - private void backupArchiveDbs(String databaseDir) throws IOException { - String bakDir = String.format("%s%s%s%d", - databaseDir, File.separator, BACKUP_DIR_PREFIX, START_TIME); - logger.info("Backup the archive dbs to {}.", bakDir); - if (!FileUtil.createDirIfNotExists(bakDir)) { - throw new RuntimeException(String.format("create bak dir %s failed", bakDir)); - } - Util.copyDatabases(Paths.get(databaseDir), Paths.get(bakDir), archiveDbs); - archiveDbs.forEach(db -> FileUtil.deleteDir(new File(databaseDir, db))); - } - - private void copyHistory2Database(String historyDir, String databaseDir) throws IOException { - logger.info("Begin to copy history to database."); - Util.copyDatabases(Paths.get(historyDir), Paths.get(databaseDir), archiveDbs); - } - - private void trimHistory(String databaseDir, BlockNumInfo blockNumInfo) - throws BadItemException, IOException, RocksDBException { - logger.info("Begin to trim the history data."); - DBInterface blockIndexDb = DbTool.getDB(databaseDir, BLOCK_INDEX_DB_NAME); - DBInterface blockDb = DbTool.getDB(databaseDir, BLOCK_DB_NAME); - DBInterface transDb = DbTool.getDB(databaseDir, TRANS_DB_NAME); - DBInterface tranRetDb = DbTool.getDB(databaseDir, TRANSACTION_RET_DB_NAME); - for (long n = blockNumInfo.getHistoryBlkNum(); n > blockNumInfo.getSnapshotBlkNum(); n--) { - byte[] blockIdHash = blockIndexDb.get(ByteArray.fromLong(n)); - BlockCapsule block = new BlockCapsule(blockDb.get(blockIdHash)); - // delete transactions - for (TransactionCapsule e : block.getTransactions()) { - transDb.delete(e.getTransactionId().getBytes()); - } - // delete transaction result - tranRetDb.delete(ByteArray.fromLong(n)); - // delete block - blockDb.delete(blockIdHash); - // delete block index - blockIndexDb.delete(ByteArray.fromLong(n)); - } - } - - private void mergeBak2Database(String databaseDir) throws IOException, RocksDBException { - String bakDir = String.format("%s%s%s%d", - databaseDir, File.separator, BACKUP_DIR_PREFIX, START_TIME); - logger.info("Begin to merge {} to database.", bakDir); - for (String dbName : archiveDbs) { - DBInterface bakDb = DbTool.getDB(bakDir, dbName); - DBInterface destDb = DbTool.getDB(databaseDir, dbName); - try (DBIterator iterator = bakDb.iterator()) { - for (iterator.seekToFirst(); iterator.hasNext(); iterator.next()) { - destDb.put(iterator.getKey(), iterator.getValue()); - } - } - } - } - - private byte[] getDataFromSourceDB(String sourceDir, String dbName, byte[] key) - throws IOException, RocksDBException { - DBInterface sourceDb = DbTool.getDB(sourceDir, dbName); - DBInterface checkpointDb = DbTool.getDB(sourceDir, CHECKPOINT_DB); - // get data from tmp first. - byte[] valueFromTmp = checkpointDb.get(Bytes.concat(simpleEncode(dbName), key)); - byte[] value; - if (isEmptyBytes(valueFromTmp)) { - value = sourceDb.get(key); - } else { - value = valueFromTmp.length == 1 - ? null : Arrays.copyOfRange(valueFromTmp, 1, valueFromTmp.length); - } - if (isEmptyBytes(value)) { - throw new RuntimeException(String.format("data not found in store, dbName: %s, key: %s", - dbName, Arrays.toString(key))); - } - return value; - } - - /** - * return true if byte array is null or length is 0. - * @param b bytes - * @return true or false - */ - private static boolean isEmptyBytes(byte[] b) { - if (b != null) { - return b.length == 0; - } - return true; - } - - private void deleteSnapshotFlag(String databaseDir) throws IOException, RocksDBException { - logger.info("Delete the info file from {}.", databaseDir); - Files.delete(Paths.get(databaseDir, INFO_FILE_NAME)); - } - - private void hasEnoughBlock(String sourceDir) throws RocksDBException, IOException { - // check latest - long latest = getLatestBlockHeaderNum(sourceDir); - // check second ,skip 0; - long second = getSecondBlock(sourceDir); - if (latest - second + 1 < RECENT_BLKS) { - throw new NoSuchElementException( - String.format("At least %d blocks in block store, actual latestBlock:%d, firstBlock:%d.", - RECENT_BLKS, latest, second)); - } - } - - private boolean isLite(String databaseDir) throws RocksDBException, IOException { - return getSecondBlock(databaseDir) > 1; - } - - private long getSecondBlock(String databaseDir) throws RocksDBException, IOException { - long num = 0; - DBInterface sourceBlockIndexDb = DbTool.getDB(databaseDir, BLOCK_INDEX_DB_NAME); - DBIterator iterator = sourceBlockIndexDb.iterator(); - iterator.seek(ByteArray.fromLong(1)); - if (iterator.hasNext()) { - num = Longs.fromByteArray(iterator.getKey()); - } - return num; - } - - @VisibleForTesting - public static void setRecentBlks(long recentBlks) { - RECENT_BLKS = recentBlks; - } - - @VisibleForTesting - public static void reSetRecentBlks() { - RECENT_BLKS = 65536; - } - - private List getCheckpointV2List(String sourceDir) { - File file = new File(Paths.get(sourceDir, CHECKPOINT_DB_V2).toString()); - if (file.exists() && file.isDirectory() && file.list() != null) { - return Arrays.stream(file.list()).sorted().collect(Collectors.toList()); - } - return Lists.newArrayList(); - } - - private void run(Args argv) { - if (StringUtils.isBlank(argv.fnDataPath) || StringUtils.isBlank(argv.datasetPath)) { - throw new ParameterException("fnDataPath or datasetPath can't be null"); - } - switch (argv.operate) { - case "split": - if (Strings.isNullOrEmpty(argv.type)) { - throw new ParameterException("type can't be null when operate=split"); - } - if (SNAPSHOT_DIR_NAME.equals(argv.type)) { - generateSnapshot(argv.fnDataPath, argv.datasetPath); - } else if (HISTORY_DIR_NAME.equals(argv.type)) { - generateHistory(argv.fnDataPath, argv.datasetPath); - } else { - throw new ParameterException("not support type:" + argv.type); - } - break; - case "merge": - completeHistoryData(argv.datasetPath, argv.fnDataPath); - break; - default: - throw new ParameterException("not supportted operate:" + argv.operate); - } - DbTool.close(); - } - - /** - * main. - */ - public static void main(String[] args) { - logger.info("LiteFullNodeTool is deprecated and it will be removed in the next major release," - + " use Toolkit.jar db lite instead, parameters are fully compatible."); - Args argv = new Args(); - CommonParameter.getInstance().setValidContractProtoThreadNum(1); - LiteFullNodeTool tool = new LiteFullNodeTool(); - JCommander jct = JCommander.newBuilder() - .addObject(argv) - .build(); - jct.setProgramName("lite fullnode tool"); - try { - jct.parse(args); - if (argv.help) { - jct.usage(); - } else { - tool.run(argv); - } - } catch (Exception e) { - logger.error(e.getMessage()); - jct.usage(); - } - } - - static class Args { - @Parameter( - names = {"--operate", "-o"}, - help = true, required = true, - description = "operate: [ split | merge ]", - order = 1) - private String operate; - @Parameter(names = {"--type", "-t"}, - help = true, - description = "only used with operate=split: [ snapshot | history ]", - order = 2) - private String type; - @Parameter( - names = {"--fn-data-path"}, - help = true, required = true, - description = "the fullnode database path," - + " defined as ${storage.db.directory} in config.conf", - order = 3) - private String fnDataPath; - @Parameter( - names = {"--dataset-path"}, - help = true, required = true, - description = "dataset directory, when operation is `split`, " - + "`dataset-path` is the path that store the `Snapshot Dataset` or " - + "`History Dataset`, otherwise `dataset-path` should be " - + "the `History Dataset` path", - order = 4) - private String datasetPath; - @Parameter( - names = "--help", - help = true, - order = 5) - private boolean help; - } - - static class BlockNumInfo { - private long snapshotBlkNum; - private long historyBlkNum; - - public BlockNumInfo(long snapshotBlkNum, long historyBlkNum) { - this.snapshotBlkNum = snapshotBlkNum; - this.historyBlkNum = historyBlkNum; - } - - public long getSnapshotBlkNum() { - return snapshotBlkNum; - } - - public long getHistoryBlkNum() { - return historyBlkNum; - } - } -} - - - diff --git a/framework/src/main/java/org/tron/tool/litefullnode/README.md b/framework/src/main/java/org/tron/tool/litefullnode/README.md deleted file mode 100644 index 24357c2a99e..00000000000 --- a/framework/src/main/java/org/tron/tool/litefullnode/README.md +++ /dev/null @@ -1,109 +0,0 @@ -# Lite FullNode Tool - -## Introduction - -Lite FullNode Tool is used to split the database of a FullNode into a `Snapshot dataset` and a `History dataset`. - -- `Snapshot dataset`: the minimum dataset for quick startup of the Lite FullNode. -- `History dataset`: the archive dataset that used for historical data queries. - -Remember stop the FullNode process before any operation. This tool provides the ability to specify which dataset to split. -The two datasets are split by the `latest_block_number`. Lite FullNode that startup by `Snapshot dataset` does not support query the historical data behind the `latest_block_number`, -this tool also provides a merge function that can merge `History dataset` into the database of Lite FullNode. For more API details: [HTTP&GRPC APIs](#HTTP&GRPC-APIs) - -For more design details, please refer to: [TIP128](https://github.com/tronprotocol/tips/issues/128) - -## Usage - -### Options - -This tool provides independent cutting of `Snapshot Dataset` and `History Dataset` and a merge function. - -- `--operation | -o`: [ split | merge ] specifies the operation as either to split or to merge -- `--type | -t`: [ snapshot | history ] is used only with `split` to specify the type of the dataset to be split; snapshot refers to Snapshot Dataset and history refers to History Dataset. -- `--fn-data-path`: FullNode database directory -- `--dataset-path`: dataset directory, when operation is `split`, `dataset-path` is the path that store the `Snapshot Dataset` or `History Dataset`, -otherwise `dataset-path` should be the `History Dataset` path. - -### Example - -Start a new FullNode using the default config, then an `output-directory` will be produced in the current directory. -`output-directory` contains a sub-directory named `database` which is the database to be split. - -#### Split and get a `Snapshot` - -First, stop the FullNode and execute: -``` -// just for simplify, locate the snapshot into `/tmp` directory, -java -jar LiteFullNodeTool.jar -o split -t snapshot --fn-data-path output-directory/database --dataset-path /tmp -``` -then a `snapshot` directory will be generated in `/tmp`, pack this directory and copy it to somewhere that is ready to run a Lite Fullnode. -Do not forget rename the directory from `snapshot` to `database`. -(the default value of the storage.db.directory is `database`, make sure rename the snapshot to the specified value) - -#### Split a `History` - -If historical data query is needed, `History dataset` should be generated and merged into Lite FullNode. -``` -// just for simplify, locate the history into `/tmp` directory, -java -jar LiteFullNodeTool.jar -o split -t history --fn-data-path output-directory/database --dataset-path /tmp -``` -A `history` directory will be generated in `/tmp`, pack this directory and copy it to a Lite Fullnode. -`History dataset` always take a large storage, make sure the disk has enough volume to store the `History dataset`. - -#### Merge - -Both `History Dataset` and `Snapshot Dataset` have an info.properties file to identify the block height from which they are segmented. -Make sure that the `split_block_num` in `History Dataset` is not less than the corresponding value in the `Snapshot Dataset`. - -After getting the `History dataset`, the Lite FullNode can merge the `History dataset` and become a real FullNode. -``` -// just for simplify, assume `History dataset` is locate in /tmp -java -jar LiteFullNodeTool.jar -o merge --fn-data-path output-directory/database --dataset-path /tmp/history -``` - -### HTTP&GRPC APIs - -Some APIs are not supported on lite fullnode, here is the list: - -#### Http - -| wallet/ | walletsolidity/ | -|---|---| -| getblockbyid | getblockbyid | -| getblockbylatestnum | getblockbylatestnum | -| getblockbylimitnext | getblockbylimitnext | -| getblockbynum | getblockbynum | -| getmerkletreevoucherinfo | getmerkletreevoucherinfo | -| gettransactionbyid | gettransactionbyid | -| gettransactioncountbyblocknum | gettransactioncountbyblocknum | -| gettransactioninfobyid | gettransactioninfobyid | -| gettransactionreceiptbyid | | -| isspend | isspend | -| scanandmarknotebyivk | scanandmarknotebyivk | -| scannotebyivk | scannotebyivk | -| scannotebyovk | scannotebyovk | -| totaltransaction | | - -#### GRPC - -| protocol.Wallet | protocol.WalletSolidity | protocol.Database | -|---|---|---| -| GetBlockById | | | -| GetBlockByLatestNum | | | -| GetBlockByLatestNum2 | | | -| GetBlockByLimitNext | | | -| GetBlockByLimitNext2 | | | -| GetBlockByNum | GetBlockByNum | GetBlockByNum | -| GetBlockByNum2 | GetBlockByNum2 | | -| GetMerkleTreeVoucherInfo | GetMerkleTreeVoucherInfo | | -| GetTransactionById | GetTransactionById | | -| GetTransactionCountByBlockNum | GetTransactionCountByBlockNum | | -| GetTransactionInfoById | GetTransactionInfoById | | -| IsSpend | IsSpend | | -| ScanAndMarkNoteByIvk | ScanAndMarkNoteByIvk | | -| ScanNoteByIvk | ScanNoteByIvk | | -| ScanNoteByOvk | ScanNoteByOvk | | -| TotalTransaction | | | - -These APIs can open forcibly by set `openHistoryQueryWhenLiteFN` = true, but not recommended. \ No newline at end of file diff --git a/framework/src/main/java/org/tron/tool/litefullnode/Util.java b/framework/src/main/java/org/tron/tool/litefullnode/Util.java deleted file mode 100644 index 0e4898b8031..00000000000 --- a/framework/src/main/java/org/tron/tool/litefullnode/Util.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.tron.tool.litefullnode; - -import java.io.IOException; -import java.nio.file.FileSystemException; -import java.nio.file.FileVisitOption; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; -import java.util.List; -import lombok.extern.slf4j.Slf4j; -import org.tron.common.utils.FileUtil; - -@Slf4j(topic = "tool") -public class Util { - - /** - * Copy src to dest, if dest is a directory and already exists, throw Exception. - * - *

Note: This method is not rigorous, because all the dirs that its FileName - * is contained in List(subDirs) will be filtered, this may result in unpredictable result. - * just used in LiteFullNodeTool. - * - * @param src Path or File - * @param dest Path or File - * @param subDirs only the subDirs in {@code src} will be copied - * @throws IOException IOException - */ - public static void copyDatabases(Path src, Path dest, List subDirs) - throws IOException { - // create subdirs, as using parallel() to run, so should create dirs first. - subDirs.forEach(dir -> { - if (FileUtil.isExists(Paths.get(src.toString(), dir).toString())) { - try { - Files.walk(Paths.get(src.toString(), dir), FileVisitOption.FOLLOW_LINKS) - .forEach(source -> copy(source, dest.resolve(src.relativize(source)))); - } catch (IOException e) { - logger.error("copy database failed, src: {}, dest: {}, error: {}", - Paths.get(src.toString(), dir), Paths.get(dest.toString(), dir), e.getMessage()); - throw new RuntimeException(e); - } - } - }); - } - - public static void copy(Path source, Path dest) { - try { - // create hard link when file is .sst - if (source.toString().endsWith(".sst")) { - try { - Files.createLink(dest, source); - } catch (FileSystemException e) { - Files.copy(source, dest, StandardCopyOption.REPLACE_EXISTING); - } - } else { - Files.copy(source, dest, StandardCopyOption.REPLACE_EXISTING); - } - } catch (Exception e) { - throw new RuntimeException(e.getMessage(), e); - } - } -} diff --git a/framework/src/main/java/org/tron/tool/litefullnode/db/DBInterface.java b/framework/src/main/java/org/tron/tool/litefullnode/db/DBInterface.java deleted file mode 100644 index 8f30cbc5026..00000000000 --- a/framework/src/main/java/org/tron/tool/litefullnode/db/DBInterface.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.tron.tool.litefullnode.db; - -import java.io.Closeable; -import java.io.IOException; -import org.tron.tool.litefullnode.iterator.DBIterator; - -public interface DBInterface extends Closeable { - - byte[] get(byte[] key); - - void put(byte[] key, byte[] value); - - void delete(byte[] key); - - DBIterator iterator(); - - long size(); - - void close() throws IOException; - -} diff --git a/framework/src/main/java/org/tron/tool/litefullnode/db/LevelDBImpl.java b/framework/src/main/java/org/tron/tool/litefullnode/db/LevelDBImpl.java deleted file mode 100644 index 774c9a86146..00000000000 --- a/framework/src/main/java/org/tron/tool/litefullnode/db/LevelDBImpl.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.tron.tool.litefullnode.db; - -import com.google.common.collect.Streams; -import java.io.IOException; -import org.iq80.leveldb.DB; -import org.tron.tool.litefullnode.iterator.DBIterator; -import org.tron.tool.litefullnode.iterator.LevelDBIterator; - -public class LevelDBImpl implements DBInterface { - - private DB leveldb; - - public LevelDBImpl(DB leveldb) { - this.leveldb = leveldb; - } - - @Override - public byte[] get(byte[] key) { - return leveldb.get(key); - } - - @Override - public void put(byte[] key, byte[] value) { - leveldb.put(key, value); - } - - @Override - public void delete(byte[] key) { - leveldb.delete(key); - } - - @Override - public DBIterator iterator() { - return new LevelDBIterator(leveldb.iterator()); - } - - @Override - public long size() { - return Streams.stream(leveldb.iterator()).count(); - } - - @Override - public void close() throws IOException { - leveldb.close(); - } -} diff --git a/framework/src/main/java/org/tron/tool/litefullnode/db/RocksDBImpl.java b/framework/src/main/java/org/tron/tool/litefullnode/db/RocksDBImpl.java deleted file mode 100644 index d6dfc55f1bb..00000000000 --- a/framework/src/main/java/org/tron/tool/litefullnode/db/RocksDBImpl.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.tron.tool.litefullnode.db; - -import com.google.common.collect.Streams; -import java.io.IOException; -import org.rocksdb.RocksDBException; -import org.rocksdb.RocksIterator; -import org.tron.tool.litefullnode.iterator.DBIterator; -import org.tron.tool.litefullnode.iterator.RockDBIterator; - -public class RocksDBImpl implements DBInterface { - - private org.rocksdb.RocksDB rocksDB; - - public RocksDBImpl(org.rocksdb.RocksDB rocksDB) { - this.rocksDB = rocksDB; - } - - @Override - public byte[] get(byte[] key) { - try { - return rocksDB.get(key); - } catch (RocksDBException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public void put(byte[] key, byte[] value) { - try { - rocksDB.put(key, value); - } catch (RocksDBException e) { - e.printStackTrace(); - } - } - - @Override - public void delete(byte[] key) { - try { - rocksDB.delete(key); - } catch (RocksDBException e) { - e.printStackTrace(); - } - } - - @Override - public DBIterator iterator() { - return new RockDBIterator(rocksDB.newIterator()); - } - - @Override - public long size() { - RocksIterator iterator = rocksDB.newIterator(); - long size = 0; - for (iterator.seekToFirst(); iterator.isValid(); iterator.next()) { - size++; - } - iterator.close(); - return size; - } - - @Override - public void close() throws IOException { - rocksDB.close(); - } -} diff --git a/framework/src/main/java/org/tron/tool/litefullnode/iterator/DBIterator.java b/framework/src/main/java/org/tron/tool/litefullnode/iterator/DBIterator.java deleted file mode 100644 index 363252e660e..00000000000 --- a/framework/src/main/java/org/tron/tool/litefullnode/iterator/DBIterator.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.tron.tool.litefullnode.iterator; - -import java.io.Closeable; - -public interface DBIterator extends Closeable { - - void seek(byte[] key); - - void seekToFirst(); - - boolean hasNext(); - - byte[] getKey(); - - byte[] getValue(); - - void next(); -} diff --git a/framework/src/main/java/org/tron/tool/litefullnode/iterator/LevelDBIterator.java b/framework/src/main/java/org/tron/tool/litefullnode/iterator/LevelDBIterator.java deleted file mode 100644 index d75b21ce67e..00000000000 --- a/framework/src/main/java/org/tron/tool/litefullnode/iterator/LevelDBIterator.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.tron.tool.litefullnode.iterator; - -import java.io.IOException; - -public class LevelDBIterator implements DBIterator { - - private org.iq80.leveldb.DBIterator iterator; - - public LevelDBIterator(org.iq80.leveldb.DBIterator iterator) { - this.iterator = iterator; - } - - @Override - public void seek(byte[] key) { - iterator.seek(key); - } - - @Override - public void seekToFirst() { - iterator.seekToFirst(); - } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public byte[] getKey() { - return iterator.peekNext().getKey(); - } - - @Override - public byte[] getValue() { - return iterator.peekNext().getValue(); - } - - @Override - public void next() { - iterator.next(); - } - - @Override - public void close() throws IOException { - iterator.close(); - } -} diff --git a/framework/src/main/java/org/tron/tool/litefullnode/iterator/RockDBIterator.java b/framework/src/main/java/org/tron/tool/litefullnode/iterator/RockDBIterator.java deleted file mode 100644 index eb13330ebce..00000000000 --- a/framework/src/main/java/org/tron/tool/litefullnode/iterator/RockDBIterator.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.tron.tool.litefullnode.iterator; - -import java.io.IOException; -import org.rocksdb.RocksIterator; - -public class RockDBIterator implements DBIterator { - - private RocksIterator iterator; - - public RockDBIterator(RocksIterator iterator) { - this.iterator = iterator; - } - - @Override - public void seek(byte[] key) { - iterator.seek(key); - } - - @Override - public void seekToFirst() { - iterator.seekToFirst(); - } - - @Override - public boolean hasNext() { - return iterator.isValid(); - } - - @Override - public byte[] getKey() { - return iterator.key(); - } - - @Override - public byte[] getValue() { - return iterator.value(); - } - - @Override - public void next() { - iterator.next(); - } - - @Override - public void close() throws IOException { - iterator.close(); - } -} diff --git a/framework/src/test/java/org/tron/core/actuator/ActuatorFactoryTest.java b/framework/src/test/java/org/tron/core/actuator/ActuatorFactoryTest.java new file mode 100644 index 00000000000..8258fbf9a3e --- /dev/null +++ b/framework/src/test/java/org/tron/core/actuator/ActuatorFactoryTest.java @@ -0,0 +1,71 @@ +package org.tron.core.actuator; + +import com.google.protobuf.ByteString; +import java.util.List; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.BaseTest; +import org.tron.common.utils.ByteArray; +import org.tron.core.Constant; +import org.tron.core.Wallet; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.config.args.Args; +import org.tron.protos.Protocol.AccountType; +import org.tron.protos.contract.BalanceContract.TransferContract; + +public class ActuatorFactoryTest extends BaseTest { + + private static final String OWNER_ADDRESS = Wallet.getAddressPreFixString() + + "548794500882809695a8a687866e76d4271a1abc"; + private static final String TO_ADDRESS = Wallet.getAddressPreFixString() + + "abd4b9367799eaa3197fecb144eb71de1e049abc"; + + static { + Args.setParam( + new String[] { + "--output-directory", dbPath() + }, + Constant.TEST_CONF + ); + } + + private TransferContract getContract(long count, String owneraddress, String toaddress) { + return TransferContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(owneraddress))) + .setToAddress(ByteString.copyFrom(ByteArray.fromHexString(toaddress))) + .setAmount(count) + .build(); + } + + @Before + public void createCapsule() { + AccountCapsule ownerCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("owner"), + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + AccountType.Normal, + 10000L); + AccountCapsule toAccountCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("toAccount"), + ByteString.copyFrom(ByteArray.fromHexString(TO_ADDRESS)), + AccountType.Normal, + 10L); + dbManager.getAccountStore().put(ownerCapsule.getAddress().toByteArray(), ownerCapsule); + dbManager.getAccountStore().put(toAccountCapsule.getAddress().toByteArray(), toAccountCapsule); + } + + + @Test + public void testCreateActuator() { + TransferContract contract = getContract(10L, OWNER_ADDRESS, TO_ADDRESS); + TransactionCapsule trx = new TransactionCapsule(contract, + chainBaseManager.getAccountStore()); + List actList = ActuatorFactory.createActuator(trx, chainBaseManager); + + Assert.assertEquals(1, actList.size()); + } + +} diff --git a/framework/src/test/java/org/tron/core/db/AccountTraceStoreTest.java b/framework/src/test/java/org/tron/core/db/AccountTraceStoreTest.java index aa87f903ad3..5a6d44a8c7c 100644 --- a/framework/src/test/java/org/tron/core/db/AccountTraceStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/AccountTraceStoreTest.java @@ -12,6 +12,7 @@ import org.tron.common.utils.ByteArray; import org.tron.core.Constant; import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.AccountTraceCapsule; import org.tron.core.config.args.Args; import org.tron.core.exception.BadItemException; import org.tron.core.exception.ItemNotFoundException; @@ -54,4 +55,16 @@ public void testGetPrevBalance() { Assert.assertEquals((long)pair2.getKey(),3L); Assert.assertEquals((long)pair2.getValue(), 99L); } + + @Test + public void testPut() { + long number = 2 ^ Long.MAX_VALUE; + long balance = 9999; + byte[] key = Bytes.concat(address, Longs.toByteArray(number)); + accountTraceStore.put(key, new AccountTraceCapsule(balance)); + Pair pair = accountTraceStore.getPrevBalance(address,2); + Assert.assertEquals((long)pair.getKey(),2L); + Assert.assertEquals((long)pair.getValue(), 0L); + } + } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/db/BlockIndexStoreTest.java b/framework/src/test/java/org/tron/core/db/BlockIndexStoreTest.java new file mode 100644 index 00000000000..a5600b34b26 --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/BlockIndexStoreTest.java @@ -0,0 +1,64 @@ +package org.tron.core.db; + +import com.google.protobuf.ByteString; +import javax.annotation.Resource; +import org.junit.Assert; +import org.junit.Test; +import org.tron.common.BaseTest; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.Constant; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.BytesCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.exception.ItemNotFoundException; + +public class BlockIndexStoreTest extends BaseTest { + + @Resource + private BlockIndexStore blockIndexStore; + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath() + }, + Constant.TEST_CONF + ); + } + + private BlockCapsule getBlockCapsule(long number) { + return new BlockCapsule(number, Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), ByteString.EMPTY); + } + + @Test + public void testPut() { + BlockCapsule blockCapsule = getBlockCapsule(1); + blockIndexStore.put(blockCapsule.getBlockId()); + byte[] key = ByteArray.fromLong(blockCapsule.getBlockId().getNum()); + Assert.assertTrue(blockIndexStore.has(key)); + } + + @Test + public void testGet() throws ItemNotFoundException { + BlockCapsule blockCapsule = getBlockCapsule(1); + blockIndexStore.put(blockCapsule.getBlockId()); + byte[] key = ByteArray.fromLong(blockCapsule.getBlockId().getNum()); + BytesCapsule bytesCapsule = blockIndexStore.get(key); + Assert.assertNotNull(bytesCapsule); + } + + @Test + public void testDelete() throws ItemNotFoundException { + BlockCapsule blockCapsule = getBlockCapsule(1); + blockIndexStore.put(blockCapsule.getBlockId()); + byte[] key = ByteArray.fromLong(blockCapsule.getBlockId().getNum()); + BytesCapsule bytesCapsule = blockIndexStore.get(key); + Assert.assertNotNull(bytesCapsule); + + blockIndexStore.delete(key); + BytesCapsule capsule = blockIndexStore.getUnchecked(key); + Assert.assertNull(capsule.getData()); + } +} diff --git a/framework/src/test/java/org/tron/core/db/BlockStoreTest.java b/framework/src/test/java/org/tron/core/db/BlockStoreTest.java index 4f706a97dcf..937a102193f 100644 --- a/framework/src/test/java/org/tron/core/db/BlockStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/BlockStoreTest.java @@ -1,21 +1,90 @@ package org.tron.core.db; +import com.google.protobuf.ByteString; +import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; import org.junit.Test; import org.tron.common.BaseTest; +import org.tron.common.utils.Sha256Hash; import org.tron.core.Constant; +import org.tron.core.capsule.BlockCapsule; import org.tron.core.config.args.Args; +import org.tron.core.exception.BadItemException; +import org.tron.core.exception.ItemNotFoundException; + @Slf4j public class BlockStoreTest extends BaseTest { + @Resource + private BlockStore blockStore; static { Args.setParam(new String[]{"--output-directory", dbPath()}, Constant.TEST_CONF); } + private BlockCapsule getBlockCapsule(long number) { + return new BlockCapsule(number, Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), ByteString.EMPTY); + } + @Test public void testCreateBlockStore() { } + + @Test + public void testPut() { + long number = 1; + BlockCapsule blockCapsule = getBlockCapsule(number); + + byte[] blockId = blockCapsule.getBlockId().getBytes(); + blockStore.put(blockId, blockCapsule); + try { + BlockCapsule blockCapsule1 = blockStore.get(blockId); + Assert.assertNotNull(blockCapsule1); + Assert.assertEquals(number, blockCapsule1.getNum()); + } catch (ItemNotFoundException | BadItemException e) { + e.printStackTrace(); + } + } + + @Test + public void testGet() { + long number = 2; + BlockCapsule blockCapsule = getBlockCapsule(number); + byte[] blockId = blockCapsule.getBlockId().getBytes(); + blockStore.put(blockId, blockCapsule); + try { + boolean has = blockStore.has(blockId); + Assert.assertTrue(has); + BlockCapsule blockCapsule1 = blockStore.get(blockId); + + Assert.assertEquals(number, blockCapsule1.getNum()); + } catch (ItemNotFoundException | BadItemException e) { + e.printStackTrace(); + } + } + + @Test + public void testDelete() { + long number = 1; + BlockCapsule blockCapsule = getBlockCapsule(number); + + byte[] blockId = blockCapsule.getBlockId().getBytes(); + blockStore.put(blockId, blockCapsule); + try { + BlockCapsule blockCapsule1 = blockStore.get(blockId); + Assert.assertNotNull(blockCapsule1); + Assert.assertEquals(number, blockCapsule1.getNum()); + + blockStore.delete(blockId); + BlockCapsule blockCapsule2 = blockStore.getUnchecked(blockId); + Assert.assertNull(blockCapsule2); + } catch (ItemNotFoundException | BadItemException e) { + e.printStackTrace(); + } + } + } diff --git a/framework/src/test/java/org/tron/core/db/DelegatedResourceStoreTest.java b/framework/src/test/java/org/tron/core/db/DelegatedResourceStoreTest.java index 8878ff0dcf3..905ef0384f1 100644 --- a/framework/src/test/java/org/tron/core/db/DelegatedResourceStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/DelegatedResourceStoreTest.java @@ -57,6 +57,21 @@ public void testPut() { Assert.assertEquals(BALANCE, delegatedResourceCapsule1.getFrozenBalanceForEnergy()); } + @Test + public void testDelete() { + DelegatedResourceCapsule delegatedResourceCapsule = create("444444444"); + byte[] key = delegatedResourceCapsule.createDbKey(); + delegatedResourceStore.put(key, delegatedResourceCapsule); + DelegatedResourceCapsule delegatedResourceCapsule1 = delegatedResourceStore.get(key); + Assert.assertNotNull(delegatedResourceCapsule1); + Assert.assertEquals(BALANCE, delegatedResourceCapsule1.getFrozenBalanceForEnergy()); + + delegatedResourceStore.delete(key); + DelegatedResourceCapsule delegatedResourceCapsule2 = delegatedResourceStore.get(key); + Assert.assertNull(delegatedResourceCapsule2); + + } + public DelegatedResourceCapsule create(String address) { byte[] ownerAddress = ByteArray.fromHexString(address); byte[] receiverAddress = ByteArray.fromHexString(RECEIVER_ADDRESS); diff --git a/framework/src/test/java/org/tron/core/db/DelegationStoreTest.java b/framework/src/test/java/org/tron/core/db/DelegationStoreTest.java index d63015ae064..10e70a0a83b 100644 --- a/framework/src/test/java/org/tron/core/db/DelegationStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/DelegationStoreTest.java @@ -68,4 +68,21 @@ public void testPut() { Assert.assertEquals(value, actualValue); } + @Test + public void testDelete() { + long value = 20_000_000; + byte[] key = buildRewardKey(CYCLE, ByteArray.fromHexString("33333333")); + delegationStore.put(key, new BytesCapsule(ByteArray + .fromLong(20_000_000))); + + BytesCapsule bytesCapsule = delegationStore.get(key); + Assert.assertNotNull(bytesCapsule); + long actualValue = ByteArray.toLong(bytesCapsule.getData()); + Assert.assertEquals(value, actualValue); + + delegationStore.delete(key); + BytesCapsule bytesCapsule1 = delegationStore.getUnchecked(key); + Assert.assertNull(bytesCapsule1.getData()); + } + } diff --git a/framework/src/test/java/org/tron/core/db/ExchangeStoreTest.java b/framework/src/test/java/org/tron/core/db/ExchangeStoreTest.java index f48ac11301d..685c137422c 100644 --- a/framework/src/test/java/org/tron/core/db/ExchangeStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/ExchangeStoreTest.java @@ -10,6 +10,7 @@ import org.tron.core.Constant; import org.tron.core.capsule.ExchangeCapsule; import org.tron.core.config.args.Args; +import org.tron.core.exception.ItemNotFoundException; import org.tron.core.store.ExchangeStore; import org.tron.protos.Protocol; @@ -50,6 +51,30 @@ public void testGet() throws Exception { Assert.assertEquals(result.getID(), 1); } + @Test + public void testPut() throws ItemNotFoundException { + Protocol.Exchange.Builder builder = Protocol.Exchange.newBuilder(); + builder.setExchangeId(1L).setCreatorAddress(ByteString.copyFromUtf8("Address1")); + ExchangeCapsule exchangeCapsule = new ExchangeCapsule(builder.build()); + exchangeKey1 = exchangeCapsule.createDbKey(); + chainBaseManager.getExchangeStore().put(exchangeKey1, exchangeCapsule); + + final ExchangeCapsule result = exchangeStore.get(exchangeKey1); + Assert.assertNotNull(result); + Assert.assertEquals(result.getID(), 1); + } + + @Test + public void testDelete() throws Exception { + final ExchangeCapsule result = exchangeStore.get(exchangeKey1); + Assert.assertNotNull(result); + Assert.assertEquals(result.getID(), 1); + + exchangeStore.delete(exchangeKey1); + ExchangeCapsule exchangeCapsule = exchangeStore.getUnchecked(exchangeKey1); + Assert.assertNull(exchangeCapsule); + } + @Test public void testGetAllExchanges() { List exchangeCapsuleList = exchangeStore.getAllExchanges(); diff --git a/framework/src/test/java/org/tron/core/db/ExchangeV2StoreTest.java b/framework/src/test/java/org/tron/core/db/ExchangeV2StoreTest.java index 2b1e2ea31ea..97c5f599b6e 100644 --- a/framework/src/test/java/org/tron/core/db/ExchangeV2StoreTest.java +++ b/framework/src/test/java/org/tron/core/db/ExchangeV2StoreTest.java @@ -8,6 +8,7 @@ import org.tron.core.Constant; import org.tron.core.capsule.ExchangeCapsule; import org.tron.core.config.args.Args; +import org.tron.core.exception.ItemNotFoundException; import org.tron.core.store.ExchangeV2Store; import org.tron.protos.Protocol; @@ -33,6 +34,31 @@ public void testGet() throws Exception { Assert.assertEquals(result.getID(), 1); } + @Test + public void testPut() throws ItemNotFoundException { + Protocol.Exchange.Builder builder = Protocol.Exchange.newBuilder().setExchangeId(1L) + .setCreatorAddress(ByteString.copyFromUtf8("Address2")); + ExchangeCapsule exchangeCapsule = new ExchangeCapsule(builder.build()); + byte[] exchangeKey1 = exchangeCapsule.createDbKey(); + exchangeV2Store.put(exchangeKey1, exchangeCapsule); + + final ExchangeCapsule result = exchangeV2Store.get(exchangeKey1); + Assert.assertNotNull(result); + Assert.assertEquals(result.getID(), 1); + } + + @Test + public void testDelete() throws ItemNotFoundException { + Protocol.Exchange.Builder builder = Protocol.Exchange.newBuilder().setExchangeId(1L) + .setCreatorAddress(ByteString.copyFromUtf8("Address3")); + ExchangeCapsule exchangeCapsule = new ExchangeCapsule(builder.build()); + byte[] exchangeKey1 = exchangeCapsule.createDbKey(); + exchangeV2Store.put(exchangeKey1, exchangeCapsule); + exchangeV2Store.delete(exchangeKey1); + ExchangeCapsule result = exchangeV2Store.getUnchecked(exchangeKey1); + Assert.assertNull(result); + } + private byte[] putToExchangeV2() { Protocol.Exchange.Builder builder = Protocol.Exchange.newBuilder().setExchangeId(1L) .setCreatorAddress(ByteString.copyFromUtf8("Address1")); diff --git a/framework/src/test/java/org/tron/core/db/MarketAccountStoreTest.java b/framework/src/test/java/org/tron/core/db/MarketAccountStoreTest.java index 51bf1c5d7fc..ed94a64175d 100644 --- a/framework/src/test/java/org/tron/core/db/MarketAccountStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/MarketAccountStoreTest.java @@ -8,6 +8,7 @@ import org.tron.core.Constant; import org.tron.core.capsule.MarketAccountOrderCapsule; import org.tron.core.config.args.Args; +import org.tron.core.exception.ItemNotFoundException; import org.tron.core.store.MarketAccountStore; public class MarketAccountStoreTest extends BaseTest { @@ -27,6 +28,11 @@ public class MarketAccountStoreTest extends BaseTest { @Test public void testGet() throws Exception { String address = "Address1"; + + MarketAccountOrderCapsule marketAccountOrderCapsule = + marketAccountStore.getUnchecked(address.getBytes()); + Assert.assertNull(marketAccountOrderCapsule); + marketAccountStore.put(address.getBytes(), new MarketAccountOrderCapsule(ByteString.copyFrom(address.getBytes()))); final MarketAccountOrderCapsule result = marketAccountStore.get(address.getBytes()); @@ -34,4 +40,14 @@ public void testGet() throws Exception { Assert.assertEquals(result.getOwnerAddress(), ByteString.copyFrom(address.getBytes())); } + @Test + public void testPut() throws ItemNotFoundException { + String address = "Address1"; + marketAccountStore.put(address.getBytes(), + new MarketAccountOrderCapsule(ByteString.copyFrom(address.getBytes()))); + final MarketAccountOrderCapsule result = marketAccountStore.get(address.getBytes()); + Assert.assertNotNull(result); + Assert.assertEquals(result.getOwnerAddress(), ByteString.copyFrom(address.getBytes())); + } + } diff --git a/framework/src/test/java/org/tron/core/db/MarketOrderStoreTest.java b/framework/src/test/java/org/tron/core/db/MarketOrderStoreTest.java index 33126783e9a..1cfdb20da97 100644 --- a/framework/src/test/java/org/tron/core/db/MarketOrderStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/MarketOrderStoreTest.java @@ -8,6 +8,7 @@ import org.tron.core.Constant; import org.tron.core.capsule.MarketOrderCapsule; import org.tron.core.config.args.Args; +import org.tron.core.exception.ItemNotFoundException; import org.tron.core.store.MarketOrderStore; import org.tron.protos.Protocol; @@ -44,4 +45,20 @@ public void testGet() throws Exception { Assert.assertEquals(result.getBuyTokenQuantity(), 100L); } + @Test + public void testDelete() throws ItemNotFoundException { + byte[] orderId = "testDelete".getBytes(); + marketOrderStore.put(orderId, + new MarketOrderCapsule(Protocol.MarketOrder.newBuilder() + .setOrderId(ByteString.copyFrom(orderId)) + .setSellTokenId(ByteString.copyFrom("addr1".getBytes())) + .setSellTokenQuantity(200L) + .setBuyTokenId(ByteString.copyFrom("addr2".getBytes())) + .setBuyTokenQuantity(100L) + .build())); + marketOrderStore.delete(orderId); + final MarketOrderCapsule result = marketOrderStore.getUnchecked(orderId); + Assert.assertNull(result); + } + } diff --git a/framework/src/test/java/org/tron/core/db/RecentBlockStoreTest.java b/framework/src/test/java/org/tron/core/db/RecentBlockStoreTest.java new file mode 100644 index 00000000000..7856fe337a5 --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/RecentBlockStoreTest.java @@ -0,0 +1,81 @@ +package org.tron.core.db; + +import com.google.protobuf.ByteString; +import javax.annotation.Resource; +import org.junit.Assert; +import org.junit.Test; +import org.tron.common.BaseTest; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.Constant; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.BytesCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.exception.ItemNotFoundException; + +public class RecentBlockStoreTest extends BaseTest { + + @Resource + private RecentBlockStore recentBlockStore; + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath() + }, + Constant.TEST_CONF + ); + } + + private BlockCapsule getBlockCapsule() { + long number = 1; + return new BlockCapsule(number, + Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), + ByteString.EMPTY); + } + + @Test + public void testPut() { + BlockCapsule blockCapsule = getBlockCapsule(); + byte[] key = ByteArray.subArray( + ByteArray.fromLong(blockCapsule.getNum()), 6, 8); + recentBlockStore.put(key, + new BytesCapsule(ByteArray.subArray(blockCapsule + .getBlockId().getBytes(), + 8, + 16))); + + Assert.assertTrue(recentBlockStore.has(key)); + } + + @Test + public void testGet() throws ItemNotFoundException { + BlockCapsule blockCapsule = getBlockCapsule(); + byte[] key = ByteArray.subArray( + ByteArray.fromLong(blockCapsule.getNum()), 6, 8); + BytesCapsule value = new BytesCapsule(ByteArray + .subArray(blockCapsule.getBlockId().getBytes(), + 8, + 16)); + recentBlockStore.put(key, value); + + BytesCapsule bytesCapsule = recentBlockStore.get(key); + Assert.assertNotNull(bytesCapsule); + Assert.assertArrayEquals(value.getData(), bytesCapsule.getData()); + } + + @Test + public void testDelete() { + BlockCapsule blockCapsule = getBlockCapsule(); + byte[] key = ByteArray.subArray( + ByteArray.fromLong(blockCapsule.getNum()), 6, 8); + recentBlockStore.put(key, + new BytesCapsule(ByteArray.subArray(blockCapsule + .getBlockId().getBytes(), + 8, + 16))); + recentBlockStore.delete(key); + Assert.assertFalse(recentBlockStore.has(key)); + } +} diff --git a/framework/src/test/java/org/tron/core/db/RecentTransactionStoreTest.java b/framework/src/test/java/org/tron/core/db/RecentTransactionStoreTest.java new file mode 100644 index 00000000000..20447dfc6a1 --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/RecentTransactionStoreTest.java @@ -0,0 +1,72 @@ +package org.tron.core.db; + +import com.google.protobuf.ByteString; +import javax.annotation.Resource; + +import org.junit.Assert; +import org.junit.Test; +import org.tron.common.BaseTest; +import org.tron.common.utils.ByteArray; +import org.tron.core.Constant; +import org.tron.core.capsule.BytesCapsule; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.exception.ItemNotFoundException; +import org.tron.protos.Protocol; +import org.tron.protos.contract.BalanceContract; + +public class RecentTransactionStoreTest extends BaseTest { + + @Resource + private RecentTransactionStore recentTransactionStore; + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath() + }, + Constant.TEST_CONF + ); + } + + private TransactionCapsule createTransaction() { + BalanceContract.TransferContract tc = + BalanceContract.TransferContract.newBuilder() + .setAmount(10) + .setOwnerAddress(ByteString.copyFromUtf8("aaa")) + .setToAddress(ByteString.copyFromUtf8("bbb")) + .build(); + return new TransactionCapsule(tc, + Protocol.Transaction.Contract.ContractType.TransferContract); + } + + + @Test + public void testPut() { + TransactionCapsule transaction = createTransaction(); + byte[] key = transaction.getTransactionId().getBytes(); + BytesCapsule value = new BytesCapsule(ByteArray.subArray(transaction + .getTransactionId().getBytes(), + 8, + 16)); + recentTransactionStore.put(key, value); + Assert.assertTrue(recentTransactionStore.has(key)); + } + + @Test + public void testGet() throws ItemNotFoundException { + TransactionCapsule transaction = createTransaction(); + byte[] key = transaction.getTransactionId().getBytes(); + BytesCapsule value = new BytesCapsule( + ByteArray.subArray(transaction + .getTransactionId().getBytes(), + 8, + 16)); + recentTransactionStore.put(key, value); + + BytesCapsule bytesCapsule = recentTransactionStore.get(key); + Assert.assertNotNull(bytesCapsule); + Assert.assertArrayEquals(value.getData(), bytesCapsule.getData()); + + } +} diff --git a/framework/src/test/java/org/tron/core/db/TransactionHistoryTest.java b/framework/src/test/java/org/tron/core/db/TransactionHistoryTest.java index eef168938b2..c5c249b6f70 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionHistoryTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionHistoryTest.java @@ -59,4 +59,11 @@ public void get() throws BadItemException { Assert.assertEquals(ByteArray.toHexString(transactionId), ByteArray.toHexString(resultCapsule.getId())); } + + @Test + public void testDelete() throws BadItemException { + transactionHistoryStore.delete(transactionId); + TransactionInfoCapsule transactionInfoCapsule = transactionHistoryStore.get(transactionId); + Assert.assertNull(transactionInfoCapsule); + } } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/db/ZKProofStoreTest.java b/framework/src/test/java/org/tron/core/db/ZKProofStoreTest.java new file mode 100644 index 00000000000..a8aa07c4342 --- /dev/null +++ b/framework/src/test/java/org/tron/core/db/ZKProofStoreTest.java @@ -0,0 +1,58 @@ +package org.tron.core.db; + +import com.google.protobuf.ByteString; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.tron.common.BaseTest; +import org.tron.core.Constant; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.store.ZKProofStore; +import org.tron.protos.Protocol; +import org.tron.protos.contract.BalanceContract; + +public class ZKProofStoreTest extends BaseTest { + + static { + Args.setParam(new String[]{"--output-directory", dbPath()}, + Constant.TEST_CONF); + } + + @Autowired + private ZKProofStore proofStore; + + private TransactionCapsule getTransactionCapsule() { + BalanceContract.TransferContract transferContract = + BalanceContract.TransferContract.newBuilder() + .setAmount(10) + .setOwnerAddress(ByteString.copyFromUtf8("aaa")) + .setToAddress(ByteString.copyFromUtf8("bbb")) + .build(); + return new TransactionCapsule(transferContract, + Protocol.Transaction.Contract.ContractType.TransferContract); + } + + @Test + public void testPut() { + TransactionCapsule trx = getTransactionCapsule(); + proofStore.put(trx.getTransactionId().getBytes(), + true); + boolean has = proofStore.has(trx.getTransactionId().getBytes()); + Assert.assertTrue(has); + } + + @Test + public void testGet() { + TransactionCapsule trx = getTransactionCapsule(); + proofStore.put(trx.getTransactionId().getBytes(), + true); + Boolean result = proofStore.get(trx.getTransactionId().getBytes()); + Assert.assertEquals(true, result); + + proofStore.put(trx.getTransactionId().getBytes(), + false); + result = proofStore.get(trx.getTransactionId().getBytes()); + Assert.assertEquals(false, result); + } +} diff --git a/framework/src/test/java/org/tron/core/services/http/ClearABIServletTest.java b/framework/src/test/java/org/tron/core/services/http/ClearABIServletTest.java new file mode 100644 index 00000000000..a3a051ec6c9 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/ClearABIServletTest.java @@ -0,0 +1,92 @@ +package org.tron.core.services.http; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.tron.common.utils.client.utils.HttpMethed.createRequest; + +import com.alibaba.fastjson.JSONObject; +import com.google.protobuf.ByteString; + +import java.io.UnsupportedEncodingException; +import javax.annotation.Resource; + +import org.apache.http.client.methods.HttpPost; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.tron.common.BaseTest; +import org.tron.common.utils.ByteArray; +import org.tron.core.Constant; +import org.tron.core.capsule.ContractCapsule; +import org.tron.core.config.args.Args; +import org.tron.protos.contract.SmartContractOuterClass; + +public class ClearABIServletTest extends BaseTest { + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath(), + }, Constant.TEST_CONF + ); + } + + @Resource + private ClearABIServlet clearABIServlet; + + private static final String SMART_CONTRACT_NAME = "smart_contract_test"; + private static String CONTRACT_ADDRESS = "A0B4750E2CD76E19DCA331BF5D089B71C3C2798548"; + private static String OWNER_ADDRESS; + private static final long SOURCE_ENERGY_LIMIT = 10L; + + + + private SmartContractOuterClass.SmartContract.Builder createContract( + String contractAddress, String contractName) { + OWNER_ADDRESS = + "A099357684BC659F5166046B56C95A0E99F1265CBD"; + SmartContractOuterClass.SmartContract.Builder builder = + SmartContractOuterClass.SmartContract.newBuilder(); + builder.setName(contractName); + builder.setOriginAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); + builder.setContractAddress(ByteString.copyFrom(ByteArray.fromHexString(contractAddress))); + builder.setOriginEnergyLimit(SOURCE_ENERGY_LIMIT); + return builder; + } + + @Test + public void testClearABI() { + chainBaseManager.getDynamicPropertiesStore() + .saveAllowTvmConstantinople(1); + SmartContractOuterClass.SmartContract.Builder contract = + createContract(CONTRACT_ADDRESS, SMART_CONTRACT_NAME); + chainBaseManager.getContractStore().put( + ByteArray.fromHexString(CONTRACT_ADDRESS), + new ContractCapsule(contract.build())); + + String jsonParam = "{" + + " \"owner_address\": \"A099357684BC659F5166046B56C95A0E99F1265CBD\"," + + " \"contract_address\": \"A0B4750E2CD76E19DCA331BF5D089B71C3C2798548\"" + + "}"; + MockHttpServletRequest request = createRequest(HttpPost.METHOD_NAME); + request.setContentType("application/json"); + request.setContent(jsonParam.getBytes(UTF_8)); + + MockHttpServletResponse response = new MockHttpServletResponse(); + clearABIServlet.doPost(request, response); + Assert.assertEquals(200, response.getStatus()); + try { + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + assertTrue(result.containsKey("raw_data")); + assertTrue(result.containsKey("txID")); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + + } + +} diff --git a/framework/src/test/java/org/tron/core/services/http/CreateAccountServletTest.java b/framework/src/test/java/org/tron/core/services/http/CreateAccountServletTest.java new file mode 100644 index 00000000000..bbc00ce81f0 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/CreateAccountServletTest.java @@ -0,0 +1,75 @@ +package org.tron.core.services.http; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.Assert.fail; +import static org.tron.common.utils.client.utils.HttpMethed.createRequest; + +import com.alibaba.fastjson.JSONObject; +import com.google.protobuf.ByteString; + +import java.io.UnsupportedEncodingException; +import javax.annotation.Resource; + +import org.apache.http.client.methods.HttpPost; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.tron.common.BaseTest; +import org.tron.common.utils.ByteArray; +import org.tron.core.Constant; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.config.args.Args; +import org.tron.protos.Protocol; + + +public class CreateAccountServletTest extends BaseTest { + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath(), + }, Constant.TEST_CONF + ); + } + + @Resource + private CreateAccountServlet createAccountServlet; + + @Before + public void init() { + AccountCapsule accountCapsule = new AccountCapsule( + ByteString.copyFrom(ByteArray + .fromHexString("A099357684BC659F5166046B56C95A0E99F1265CD1")), + ByteString.copyFromUtf8("owner"), + Protocol.AccountType.forNumber(1)); + + chainBaseManager.getAccountStore().put(accountCapsule.createDbKey(), + accountCapsule); + } + + @Test + public void testCreate() { + String jsonParam = "{" + + "\"owner_address\": \"A099357684BC659F5166046B56C95A0E99F1265CD1\"," + + "\"account_address\": \"A0B4750E2CD76E19DCA331BF5D089B71C3C2798541\"" + + "}"; + MockHttpServletRequest request = createRequest(HttpPost.METHOD_NAME); + request.setContentType("application/json"); + request.setContent(jsonParam.getBytes(UTF_8)); + + MockHttpServletResponse response = new MockHttpServletResponse(); + createAccountServlet.doPost(request, response); + + Assert.assertEquals(200, response.getStatus()); + try { + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + Assert.assertTrue(result.containsKey("raw_data")); + Assert.assertTrue(result.containsKey("txID")); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } +} diff --git a/framework/src/test/java/org/tron/core/services/http/CreateAssetIssueServletTest.java b/framework/src/test/java/org/tron/core/services/http/CreateAssetIssueServletTest.java new file mode 100644 index 00000000000..4c70eb9252c --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/CreateAssetIssueServletTest.java @@ -0,0 +1,90 @@ +package org.tron.core.services.http; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.Assert.fail; +import static org.tron.common.utils.client.utils.HttpMethed.createRequest; + +import com.alibaba.fastjson.JSONObject; +import com.google.protobuf.ByteString; + +import java.io.UnsupportedEncodingException; +import javax.annotation.Resource; + +import org.apache.http.client.methods.HttpPost; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.tron.common.BaseTest; +import org.tron.common.utils.ByteArray; +import org.tron.core.Constant; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.config.args.Args; +import org.tron.protos.Protocol; + +public class CreateAssetIssueServletTest extends BaseTest { + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath(), + }, Constant.TEST_CONF + ); + } + + @Resource + private CreateAssetIssueServlet createAssetIssueServlet; + + @Before + public void init() { + AccountCapsule accountCapsule = new AccountCapsule( + ByteString.copyFrom(ByteArray + .fromHexString("A099357684BC659F5166046B56C95A0E99F1265CD1")), + ByteString.copyFromUtf8("owner"), + Protocol.AccountType.forNumber(1)); + accountCapsule.setBalance(10000000000L); + + chainBaseManager.getAccountStore().put(accountCapsule.createDbKey(), + accountCapsule); + } + + @Test + public void testCreate() { + String jsonParam = "{" + + " \"owner_address\": \"A099357684BC659F5166046B56C95A0E99F1265CD1\"," + + " \"name\": \"0x6173736574497373756531353330383934333132313538\"," + + " \"abbr\": \"0x6162627231353330383934333132313538\"," + + " \"total_supply\": 4321," + + " \"trx_num\": 1," + + " \"num\": 1," + + " \"start_time\": 1530894315158," + + " \"end_time\": 1533894312158," + + " \"description\": \"007570646174654e616d6531353330363038383733343633\"," + + " \"url\": \"007570646174654e616d6531353330363038383733343633\"," + + " \"free_asset_net_limit\": 10000," + + " \"public_free_asset_net_limit\": 10000," + + " \"frozen_supply\": {" + + " \"frozen_amount\": 1," + + " \"frozen_days\": 2" + + " }" + + "}"; + MockHttpServletRequest request = createRequest(HttpPost.METHOD_NAME); + request.setContentType("application/json"); + request.setContent(jsonParam.getBytes(UTF_8)); + + MockHttpServletResponse response = new MockHttpServletResponse(); + createAssetIssueServlet.doPost(request, response); + Assert.assertEquals(200, response.getStatus()); + try { + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + Assert.assertTrue(result.containsKey("raw_data")); + Assert.assertTrue(result.containsKey("txID")); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + + } + +} diff --git a/framework/src/test/java/org/tron/core/services/http/CreateSpendAuthSigServletTest.java b/framework/src/test/java/org/tron/core/services/http/CreateSpendAuthSigServletTest.java new file mode 100644 index 00000000000..301e4472e69 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/CreateSpendAuthSigServletTest.java @@ -0,0 +1,60 @@ +package org.tron.core.services.http; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.Assert.fail; +import static org.tron.common.utils.client.utils.HttpMethed.createRequest; + +import com.alibaba.fastjson.JSONObject; +import java.io.UnsupportedEncodingException; +import javax.annotation.Resource; +import org.apache.http.client.methods.HttpPost; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.tron.common.BaseTest; +import org.tron.core.Constant; +import org.tron.core.config.args.Args; + +public class CreateSpendAuthSigServletTest extends BaseTest { + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath(), + }, Constant.TEST_CONF + ); + } + + @Resource + private CreateSpendAuthSigServlet createSpendAuthSigServlet; + + @Test + public void testCreateSpendAuthSig() { + String jsonParam = "{" + + " \"ask\": \"e3ebcba1531f6d9158d9c162660c5d7c04dadf77d" + + "85d7436a9c98b291ff69a09\"," + + " \"tx_hash\": \"3b78fee6e956f915ffe082284c5f18640edca9" + + "c57a5f227e5f7d7eb65ad61502\"," + + " \"alpha\": \"2608999c3a97d005a879ecdaa16fd29ae434fb67" + + "b177c5e875b0c829e6a1db04\"" + + "}"; + MockHttpServletRequest request = createRequest(HttpPost.METHOD_NAME); + request.setContentType("application/json"); + request.setContent(jsonParam.getBytes(UTF_8)); + + MockHttpServletResponse response = new MockHttpServletResponse(); + createSpendAuthSigServlet.doPost(request, response); + Assert.assertEquals(200, response.getStatus()); + try { + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + Assert.assertTrue(result.containsKey("value")); + String resultValue = (String) result.get("value"); + Assert.assertNotNull(resultValue); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } + +} diff --git a/framework/src/test/java/org/tron/core/services/http/CreateWitnessServletTest.java b/framework/src/test/java/org/tron/core/services/http/CreateWitnessServletTest.java new file mode 100644 index 00000000000..6cd6e9e2482 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/CreateWitnessServletTest.java @@ -0,0 +1,88 @@ +package org.tron.core.services.http; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.Assert.fail; +import static org.tron.common.utils.client.utils.HttpMethed.createRequest; + +import com.alibaba.fastjson.JSONObject; +import com.google.protobuf.ByteString; + +import java.io.UnsupportedEncodingException; +import javax.annotation.Resource; + +import org.apache.http.client.methods.HttpPost; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.tron.common.BaseTest; +import org.tron.common.crypto.ECKey; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Utils; +import org.tron.core.Constant; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.WitnessCapsule; +import org.tron.core.config.args.Args; +import org.tron.protos.Protocol; + +public class CreateWitnessServletTest extends BaseTest { + + @Resource + private CreateWitnessServlet createWitnessServlet; + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath(), + }, Constant.TEST_CONF + ); + } + + private static WitnessCapsule witnessCapsule; + private static AccountCapsule accountCapsule; + + @Before + public void init() { + ECKey ecKey = new ECKey(Utils.getRandom()); + ByteString address = ByteString.copyFrom(ecKey.getAddress()); + + accountCapsule = + new AccountCapsule(Protocol.Account + .newBuilder() + .setAddress(address).build()); + accountCapsule.setBalance(10000000L); + dbManager.getAccountStore().put(accountCapsule + .getAddress().toByteArray(), accountCapsule); + } + + @Test + public void testCreateWitness() { + chainBaseManager.getDynamicPropertiesStore() + .saveAccountUpgradeCost(1L); + String hexAddress = ByteArray + .toHexString(accountCapsule.getAddress().toByteArray()); + String jsonParam = "{\"owner_address\":\"" + + hexAddress + "\"," + + " \"url\": \"00757064617" + + "4654e616d6531353330363038383733343633\"}"; + MockHttpServletRequest request = createRequest(HttpPost.METHOD_NAME); + request.setContentType("application/json"); + request.setContent(jsonParam.getBytes(UTF_8)); + + MockHttpServletResponse response = new MockHttpServletResponse(); + createWitnessServlet.doPost(request, response); + Assert.assertEquals(200, response.getStatus()); + try { + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + Assert.assertTrue(result.containsKey("raw_data")); + Assert.assertTrue(result.containsKey("txID")); + } catch (UnsupportedEncodingException e) { + fail(e.getMessage()); + } + } + +} + + diff --git a/framework/src/test/java/org/tron/core/services/http/GetAccountByIdServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetAccountByIdServletTest.java new file mode 100644 index 00000000000..38c23a971ff --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/GetAccountByIdServletTest.java @@ -0,0 +1,47 @@ +package org.tron.core.services.http; + +import static org.apache.commons.lang3.StringUtils.isNotEmpty; + +import javax.annotation.Resource; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.tron.common.BaseTest; +import org.tron.core.Constant; +import org.tron.core.config.args.Args; + +public class GetAccountByIdServletTest extends BaseTest { + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath(), + }, Constant.TEST_CONF + ); + } + + @Resource + private GetAccountByIdServlet getAccountByIdServlet; + + public MockHttpServletRequest createRequest(String contentType) { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setMethod("POST"); + if (isNotEmpty(contentType)) { + request.setContentType(contentType); + } + request.setCharacterEncoding("UTF-8"); + return request; + } + + @Test + public void testGetAccountById() { + String jsonParam = "{\"account_id\": \"6161616162626262\"}"; + MockHttpServletRequest request = createRequest("application/json"); + request.setContent(jsonParam.getBytes()); + MockHttpServletResponse response = new MockHttpServletResponse(); + + getAccountByIdServlet.doPost(request, response); + Assert.assertEquals(200, response.getStatus()); + } +} diff --git a/framework/src/test/java/org/tron/core/services/http/GetBlockByIdServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetBlockByIdServletTest.java new file mode 100644 index 00000000000..8b213e12640 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/GetBlockByIdServletTest.java @@ -0,0 +1,51 @@ +package org.tron.core.services.http; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.tron.common.utils.client.utils.HttpMethed.createRequest; + +import javax.annotation.Resource; + +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.tron.common.BaseTest; +import org.tron.core.Constant; +import org.tron.core.config.args.Args; + +public class GetBlockByIdServletTest extends BaseTest { + + @Resource + private GetBlockByIdServlet getBlockByIdServlet; + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath(), + }, Constant.TEST_CONF + ); + } + + @Test + public void testGetBlockById() { + String jsonParam = "{\"value\": " + + "\"0000000002951a2f65db6725c2d0583f1ab9bdb1520eeedece99d9c98f3\"}"; + MockHttpServletRequest request = createRequest(HttpPost.METHOD_NAME); + request.setContentType("application/json"); + request.setContent(jsonParam.getBytes(UTF_8)); + MockHttpServletResponse response = new MockHttpServletResponse(); + getBlockByIdServlet.doPost(request, response); + Assert.assertEquals(200, response.getStatus()); + } + + @Test + public void testGet() { + MockHttpServletRequest request = createRequest(HttpGet.METHOD_NAME); + request.addParameter("value", "0000000002951a2f65db6725c2d0583f1ab9bdb1520eeedece99d9c98f3"); + MockHttpServletResponse response = new MockHttpServletResponse(); + getBlockByIdServlet.doGet(request, response); + Assert.assertEquals(200, response.getStatus()); + } +} diff --git a/framework/src/test/java/org/tron/core/services/http/GetBlockByNumServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetBlockByNumServletTest.java new file mode 100644 index 00000000000..5ff84c54dbe --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/GetBlockByNumServletTest.java @@ -0,0 +1,69 @@ +package org.tron.core.services.http; + +import static org.junit.Assert.assertTrue; +import static org.tron.common.utils.client.utils.HttpMethed.createRequest; + +import com.alibaba.fastjson.JSONObject; + +import java.io.UnsupportedEncodingException; +import javax.annotation.Resource; + +import org.apache.http.client.methods.HttpPost; +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.tron.common.BaseTest; +import org.tron.core.Constant; +import org.tron.core.config.args.Args; + +public class GetBlockByNumServletTest extends BaseTest { + + @Resource + private GetBlockByNumServlet getBlockByNumServlet; + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath(), + }, Constant.TEST_CONF + ); + } + + @Test + public void testGetBlockByNum() { + String jsonParam = "{\"number\": 1}"; + MockHttpServletRequest request = createRequest(HttpPost.METHOD_NAME); + request.setContentType("application/json"); + request.setContent(jsonParam.getBytes()); + MockHttpServletResponse response = new MockHttpServletResponse(); + + try { + getBlockByNumServlet.doPost(request, response); + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + assertTrue(result.containsKey("blockID")); + assertTrue(result.containsKey("transactions")); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + + @Test + public void testGet() { + String jsonParam = "{\"number\": 1}"; + MockHttpServletRequest request = createRequest("application/json"); + request.setContent(jsonParam.getBytes()); + MockHttpServletResponse response = new MockHttpServletResponse(); + + try { + getBlockByNumServlet.doPost(request, response); + String contentAsString = response.getContentAsString(); + JSONObject result = JSONObject.parseObject(contentAsString); + assertTrue(result.containsKey("blockID")); + assertTrue(result.containsKey("transactions")); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + +} diff --git a/framework/src/test/java/org/tron/core/services/http/GetTransactionInfoByBlockNumServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetTransactionInfoByBlockNumServletTest.java new file mode 100644 index 00000000000..0a1a2e4ac5a --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/GetTransactionInfoByBlockNumServletTest.java @@ -0,0 +1,79 @@ +package org.tron.core.services.http; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.tron.common.utils.client.utils.HttpMethed.createRequest; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; + +import java.io.UnsupportedEncodingException; +import javax.annotation.Resource; + +import org.apache.http.client.methods.HttpPost; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.tron.common.BaseTest; +import org.tron.common.utils.ByteArray; +import org.tron.core.Constant; + +import org.tron.core.capsule.TransactionInfoCapsule; +import org.tron.core.capsule.TransactionRetCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.db.TransactionStoreTest; + +public class GetTransactionInfoByBlockNumServletTest extends BaseTest { + + @Resource + private GetTransactionInfoByBlockNumServlet getTransactionInfoByBlockNumServlet; + private static final byte[] transactionId = TransactionStoreTest.randomBytes(32); + private static TransactionRetCapsule transactionRetCapsule; + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath(), + }, Constant.TEST_CONF + ); + } + + @Before + public void init() { + byte[] blockNum = ByteArray.fromLong(100); + TransactionInfoCapsule transactionInfoCapsule = new TransactionInfoCapsule(); + + transactionInfoCapsule.setId(transactionId); + transactionInfoCapsule.setFee(1000L); + transactionInfoCapsule.setBlockNumber(100L); + transactionInfoCapsule.setBlockTimeStamp(200L); + + transactionRetCapsule = new TransactionRetCapsule(); + transactionRetCapsule.addTransactionInfo(transactionInfoCapsule.getInstance()); + chainBaseManager.getTransactionRetStore() + .put(blockNum, transactionRetCapsule); + } + + @Test + public void testGetTransactionInfoByBlockNum() { + String jsonParam = "{\"num\" : 100}"; + MockHttpServletRequest request = createRequest(HttpPost.METHOD_NAME); + request.setContentType("application/json"); + request.setContent(jsonParam.getBytes(UTF_8)); + MockHttpServletResponse response = new MockHttpServletResponse(); + + getTransactionInfoByBlockNumServlet.doPost(request, response); + Assert.assertEquals(200, response.getStatus()); + try { + String contentAsString = response.getContentAsString(); + JSONArray array = JSONArray.parseArray(contentAsString); + Assert.assertEquals(1, array.size()); + JSONObject object = (JSONObject) array.get(0); + Assert.assertEquals(1000, object.get("fee")); + Assert.assertEquals(100, object.get("blockNumber")); + } catch (UnsupportedEncodingException e) { + Assert.fail(e.getMessage()); + } + } +} diff --git a/framework/src/test/java/org/tron/core/services/http/GetTransactionInfoByIdServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetTransactionInfoByIdServletTest.java new file mode 100644 index 00000000000..900c41c7df8 --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/GetTransactionInfoByIdServletTest.java @@ -0,0 +1,126 @@ +package org.tron.core.services.http; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.tron.common.utils.client.utils.HttpMethed.createRequest; + +import com.alibaba.fastjson.JSONObject; +import com.google.protobuf.ByteString; + +import java.io.UnsupportedEncodingException; +import javax.annotation.Resource; + +import org.apache.http.client.methods.HttpPost; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.tron.common.BaseTest; +import org.tron.common.utils.ByteArray; +import org.tron.core.Constant; +import org.tron.core.Wallet; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.capsule.TransactionInfoCapsule; +import org.tron.core.capsule.TransactionRetCapsule; +import org.tron.core.config.args.Args; +import org.tron.core.db.TransactionStore; +import org.tron.core.db.TransactionStoreTest; +import org.tron.core.store.TransactionRetStore; +import org.tron.protos.Protocol; +import org.tron.protos.contract.BalanceContract; + +public class GetTransactionInfoByIdServletTest extends BaseTest { + + @Resource + private GetTransactionInfoByIdServlet getTransactionInfoByIdServlet; + @Resource + private TransactionStore transactionStore; + @Resource + private TransactionRetStore transactionRetStore; + + private static final String OWNER_ADDRESS = + Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; + private static final String TO_ADDRESS = + Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; + private static final long AMOUNT = 100; + private static final byte[] KEY_1 = TransactionStoreTest.randomBytes(21); + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath(), + }, Constant.TEST_CONF + ); + } + + @Before + public void init() { + byte[] blockNum = ByteArray.fromLong(100); + TransactionInfoCapsule transactionInfoCapsule = new TransactionInfoCapsule(); + + transactionInfoCapsule.setId(KEY_1); + transactionInfoCapsule.setFee(1000L); + transactionInfoCapsule.setBlockNumber(100L); + transactionInfoCapsule.setBlockTimeStamp(200L); + + TransactionRetCapsule transactionRetCapsule = new TransactionRetCapsule(); + transactionRetCapsule.addTransactionInfo(transactionInfoCapsule.getInstance()); + chainBaseManager.getTransactionRetStore() + .put(blockNum, transactionRetCapsule); + transactionRetStore.put(blockNum, transactionRetCapsule); + + AccountCapsule owner = new AccountCapsule( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + ByteString.copyFromUtf8("owner"), + Protocol.AccountType.forNumber(1)); + owner.setBalance(1000000L); + + AccountCapsule to = new AccountCapsule( + ByteString.copyFrom(ByteArray.fromHexString(TO_ADDRESS)), + ByteString.copyFromUtf8("to"), + Protocol.AccountType.forNumber(1)); + to.setBalance(1000000L); + + chainBaseManager.getAccountStore().put(owner.createDbKey(), + owner); + chainBaseManager.getAccountStore().put(to.createDbKey(), + to); + BalanceContract.TransferContract transferContract = + getContract(AMOUNT, OWNER_ADDRESS, TO_ADDRESS); + TransactionCapsule transactionCapsule = new TransactionCapsule(transferContract, + chainBaseManager.getAccountStore()); + transactionCapsule.setBlockNum(100L); + transactionStore.put(KEY_1, transactionCapsule); + } + + private BalanceContract.TransferContract getContract(long count, + String owneraddress, String toaddress) { + return BalanceContract.TransferContract.newBuilder() + .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(owneraddress))) + .setToAddress(ByteString.copyFrom(ByteArray.fromHexString(toaddress))) + .setAmount(count) + .build(); + } + + @Test + public void testGetInfoById() { + String jsonParam = "{\"value\" : " + + "\"" + ByteArray.toHexString(KEY_1) + "\"}"; + MockHttpServletRequest request = createRequest(HttpPost.METHOD_NAME); + request.setContentType("application/json"); + request.setContent(jsonParam.getBytes(UTF_8)); + MockHttpServletResponse response = new MockHttpServletResponse(); + + getTransactionInfoByIdServlet.doPost(request, response); + Assert.assertEquals(200, response.getStatus()); + try { + String contentAsString = response.getContentAsString(); + JSONObject jsonObject = JSONObject.parseObject(contentAsString); + Assert.assertEquals(1000, jsonObject.get("fee")); + Assert.assertEquals(100, jsonObject.get("blockNumber")); + } catch (UnsupportedEncodingException e) { + Assert.fail(e.getMessage()); + } + } +} diff --git a/framework/src/test/java/org/tron/core/services/http/GetTransactionListFromPendingServletTest.java b/framework/src/test/java/org/tron/core/services/http/GetTransactionListFromPendingServletTest.java new file mode 100644 index 00000000000..614d520280d --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/GetTransactionListFromPendingServletTest.java @@ -0,0 +1,38 @@ +package org.tron.core.services.http; + +import static org.junit.Assert.assertEquals; +import static org.tron.common.utils.client.utils.HttpMethed.createRequest; + +import javax.annotation.Resource; + +import org.apache.http.client.methods.HttpGet; +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.tron.common.BaseTest; +import org.tron.core.Constant; +import org.tron.core.config.args.Args; + + +public class GetTransactionListFromPendingServletTest extends BaseTest { + + @Resource + private GetTransactionListFromPendingServlet getTransactionListFromPendingServlet; + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath(), + }, Constant.TEST_CONF + ); + } + + @Test + public void testGet() { + MockHttpServletRequest request = createRequest(HttpGet.METHOD_NAME); + MockHttpServletResponse response = new MockHttpServletResponse(); + getTransactionListFromPendingServlet.doPost(request, response); + assertEquals(200, response.getStatus()); + } + +} diff --git a/framework/src/test/java/org/tron/core/services/http/UpdateAccountServletTest.java b/framework/src/test/java/org/tron/core/services/http/UpdateAccountServletTest.java new file mode 100644 index 00000000000..e5064e2013b --- /dev/null +++ b/framework/src/test/java/org/tron/core/services/http/UpdateAccountServletTest.java @@ -0,0 +1,77 @@ +package org.tron.core.services.http; + +import static org.tron.common.utils.client.utils.HttpMethed.createRequest; + +import javax.annotation.Resource; +import org.apache.http.client.methods.HttpPost; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.tron.common.BaseTest; +import org.tron.core.Constant; +import org.tron.core.config.args.Args; + +public class UpdateAccountServletTest extends BaseTest { + + static { + Args.setParam( + new String[]{ + "--output-directory", dbPath(), + }, Constant.TEST_CONF + ); + } + + @Resource + private UpdateAccountServlet updateAccountServlet; + + private String getParam() { + return "{" + + " \"owner_address\": \"TXmVpin5vq5gdZsciyyjdZgKRUju4st1wM\"," + + " \"owner\": {" + + " \"type\": 0," + + " \"permission_name\": \"owner\"," + + " \"threshold\": 1," + + " \"keys\": [{" + + " \"address\": \"TXmVpin5vq5gdZsciyyjdZgKRUju4st1wM\"," + + " \"weight\": 1" + + " }]" + + " }," + + " \"witness\": {" + + " \"type\": 1," + + " \"permission_name\": \"witness\"," + + " \"threshold\": 1," + + " \"keys\": [{" + + " \"address\": \"TXmVpin5vq5gdZsciyyjdZgKRUju4st1wM\"," + + " \"weight\": 1" + + " }]" + + " }," + + " \"actives\": [{" + + " \"type\": 2," + + " \"permission_name\": \"active12323\"," + + " \"threshold\": 2," + + " \"operations\": " + + "\"7fff1fc0033e0000000000000000000000000000000000000000000000000000\"," + + " \"keys\": [{" + + " \"address\": \"TXmVpin5vq5gdZsciyyjdZgKRUju4st1wM\"," + + " \"weight\": 1" + + " }, {" + + " \"address\": \"TXmVpin5vq5gdZsciyyjdZgKRUju4st1wM\"," + + " \"weight\": 1" + + " }]" + + " }]," + + " \"visible\": true}"; + } + + @Test + public void test() { + String jsonParam = getParam(); + MockHttpServletRequest request = createRequest(HttpPost.METHOD_NAME); + request.setContentType("application/json"); + request.setContent(jsonParam.getBytes()); + MockHttpServletResponse response = new MockHttpServletResponse(); + + updateAccountServlet.doPost(request, response); + Assert.assertEquals(200, response.getStatus()); + } +} diff --git a/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java b/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java deleted file mode 100644 index d1da0bf00d8..00000000000 --- a/framework/src/test/java/org/tron/program/LiteFullNodeToolTest.java +++ /dev/null @@ -1,202 +0,0 @@ -package org.tron.program; - -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import java.io.File; -import java.nio.file.Paths; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.junit.After; -import org.junit.Test; -import org.tron.api.WalletGrpc; -import org.tron.common.application.Application; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; -import org.tron.common.config.DbBackupConfig; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.FileUtil; -import org.tron.common.utils.PublicMethod; -import org.tron.common.utils.Utils; -import org.tron.core.config.DefaultConfig; -import org.tron.core.config.args.Args; -import org.tron.core.services.RpcApiService; -import org.tron.core.services.interfaceOnSolidity.RpcApiServiceOnSolidity; -import org.tron.tool.litefullnode.LiteFullNodeTool; - -@Slf4j -@Deprecated -public class LiteFullNodeToolTest { - - private TronApplicationContext context; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; - private ManagedChannel channelFull; - private Application appTest; - private String databaseDir; - - private static String dbPath = "output_lite_fn"; - - /** - * init logic. - */ - public void startApp() { - context = new TronApplicationContext(DefaultConfig.class); - appTest = ApplicationFactory.create(context); - appTest.addService(context.getBean(RpcApiService.class)); - appTest.addService(context.getBean(RpcApiServiceOnSolidity.class)); - appTest.startup(); - - String fullNode = String.format("%s:%d", "127.0.0.1", - Args.getInstance().getRpcPort()); - channelFull = ManagedChannelBuilder.forTarget(fullNode) - .usePlaintext() - .build(); - blockingStubFull = WalletGrpc.newBlockingStub(channelFull); - } - - /** - * Delete the database when exited. - */ - public static void destroy(String dbPath) { - File f = new File(dbPath); - if (f.exists()) { - if (FileUtil.deleteDir(f)) { - logger.info("Release resources successful."); - } else { - logger.info("Release resources failure."); - } - } - } - - /** - * shutdown the fullNode. - */ - public void shutdown() throws InterruptedException { - if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); - } - context.close(); - } - - public void init() { - destroy(dbPath); // delete if prev failed - Args.setParam(new String[]{"-d", dbPath, "-w"}, "config-localtest.conf"); - // allow account root - Args.getInstance().setAllowAccountStateRoot(1); - Args.getInstance().setRpcPort(PublicMethod.chooseRandomPort()); - databaseDir = Args.getInstance().getStorage().getDbDirectory(); - // init dbBackupConfig to avoid NPE - Args.getInstance().dbBackupConfig = DbBackupConfig.getInstance(); - } - - @After - public void clear() { - destroy(dbPath); - Args.clearParam(); - dbPath = "output_lite_fn"; - } - - @Test - public void testToolsWithLevelDB() throws InterruptedException { - logger.info("testToolsWithLevelDB start"); - testTools("LEVELDB", 1); - } - - @Test - public void testToolsWithLevelDBV2() throws InterruptedException { - logger.info("testToolsWithLevelDB start"); - testTools("LEVELDB", 2); - } - - @Test - public void testToolsWithRocksDB() throws InterruptedException { - logger.info("testToolsWithRocksDB start"); - testTools("ROCKSDB", 1); - } - - private void testTools(String dbType, int checkpointVersion) - throws InterruptedException { - dbPath = String.format("%s_%s_%d", dbPath, dbType, System.currentTimeMillis()); - init(); - final String[] argsForSnapshot = - new String[]{"-o", "split", "-t", "snapshot", "--fn-data-path", - dbPath + File.separator + databaseDir, "--dataset-path", - dbPath}; - final String[] argsForHistory = - new String[]{"-o", "split", "-t", "history", "--fn-data-path", - dbPath + File.separator + databaseDir, "--dataset-path", - dbPath}; - final String[] argsForMerge = - new String[]{"-o", "merge", "--fn-data-path", dbPath + File.separator + databaseDir, - "--dataset-path", dbPath + File.separator + "history"}; - Args.getInstance().getStorage().setDbEngine(dbType); - Args.getInstance().getStorage().setCheckpointVersion(checkpointVersion); - LiteFullNodeTool.setRecentBlks(3); - // start fullNode - startApp(); - // produce transactions for 18 seconds - generateSomeTransactions(18); - // stop the node - shutdown(); - // delete tran-cache - FileUtil.deleteDir(Paths.get(dbPath, databaseDir, "trans-cache").toFile()); - // generate snapshot - LiteFullNodeTool.main(argsForSnapshot); - // start fullNode - startApp(); - // produce transactions for 6 seconds - generateSomeTransactions(6); - // stop the node - shutdown(); - // generate history - LiteFullNodeTool.main(argsForHistory); - // backup original database to database_bak - File database = new File(Paths.get(dbPath, databaseDir).toString()); - if (!database.renameTo(new File(Paths.get(dbPath, databaseDir + "_bak").toString()))) { - throw new RuntimeException( - String.format("rename %s to %s failed", database.getPath(), - Paths.get(dbPath, databaseDir))); - } - // change snapshot to the new database - File snapshot = new File(Paths.get(dbPath, "snapshot").toString()); - if (!snapshot.renameTo(new File(Paths.get(dbPath, databaseDir).toString()))) { - throw new RuntimeException( - String.format("rename snapshot to %s failed", - Paths.get(dbPath, databaseDir))); - } - // start and validate the snapshot - startApp(); - generateSomeTransactions(6); - // stop the node - shutdown(); - // merge history - LiteFullNodeTool.main(argsForMerge); - // start and validate - startApp(); - generateSomeTransactions(6); - shutdown(); - LiteFullNodeTool.reSetRecentBlks(); - } - - private void generateSomeTransactions(int during) { - during *= 1000; // ms - int runTime = 0; - int sleepOnce = 100; - while (true) { - ECKey ecKey2 = new ECKey(Utils.getRandom()); - byte[] address = ecKey2.getAddress(); - - String sunPri = "cba92a516ea09f620a16ff7ee95ce0df1d56550a8babe9964981a7144c8a784a"; - byte[] sunAddress = PublicMethod.getFinalAddress(sunPri); - PublicMethod.sendcoin(address, 1L, - sunAddress, sunPri, blockingStubFull); - try { - Thread.sleep(sleepOnce); - } catch (InterruptedException e) { - e.printStackTrace(); - } - if ((runTime += sleepOnce) > during) { - return; - } - } - } -} diff --git a/plugins/README.md b/plugins/README.md index 6807bfbb409..19c952372c1 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -66,7 +66,6 @@ DB copy provides a helper which can copy LevelDB or RocksDB data quickly on the java -jar Toolkit.jar db cp output-directory/database /tmp/databse ``` - ## DB Lite DB lite provides lite database, parameters are compatible with previous `LiteFullNodeTool`.